免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1617 | 回复: 0
打印 上一主题 下一主题

Handler Looper Message源码研究 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2011-11-22 11:02 |只看该作者 |倒序浏览
Handler Looper Message源码研究









概述

Looper是消费者,Handler是生产者,MessageQueue是消息队列,队列的实现方式是链表,Message是链表的一个节点。


线程Thread的线程变量ThreadLocal中,存放着这个线程的Looper;

Looper在初始化时,会新建一个消息队列MessageQueue,之后Looper进入一个死循环,等待从消息队列MessageQueue取得消息Message(Looper是消费者),没有消息时会阻塞;

我们程序中的Handler,会通过sendMessage或post方法,往MessageQueue中添加消息时,添加的这个Message,会记录他是属于哪个Handler发出的,同时根据message.when,决定新添加的这个Message在Queue中的位置,MessageQueue中只有一个当前的Message,队列关系是通过Message中的prev,next维护的,Message是一个链表的节点;

添加消息后,消费者Looper取得Message,并调用建立Message的Hander的dispatchMessage方法。

一个在新线程中使用handler例子,我们来分析下源码

Java代码
  1. 1.new Thread(new Runnable() {   
  2. 2.     @Override public void run() {   
  3. 3.          Handler handler;   
  4. 4.          //1、初始化Looper   
  5. 5.          Looper.prepare();   
  6. 6.          //2、绑定handler到CustomThread实例的Looper对象、定义处理消息的方法   
  7. 7.          handler= new Handler() {   
  8. 8.               @Override public void handleMessage(Message msg) {   
  9. 9.               }   
  10. 10.          };   
  11. 11.          // 3、发送消息   
  12. 12.          handler.sendMessage(new Message());   
  13. 13.          handler.post(new Runnable())   
  14. 14.          handler.obtainMessage(1, "hello").sendToTarget();   
  15. 15.          //4、启动消息循环   
  16. 16.          Looper.loop();   
  17. 17.     }   
  18. 18.}).start();  
  19. new Thread(new Runnable() {
  20.      @Override public void run() {
  21.           Handler handler;
  22.           //1、初始化Looper
  23.           Looper.prepare();
  24.           //2、绑定handler到CustomThread实例的Looper对象、定义处理消息的方法
  25.           handler= new Handler() {
  26.                @Override public void handleMessage(Message msg) {
  27.                }
  28.           };
  29.           // 3、发送消息
  30.           handler.sendMessage(new Message());
  31.           handler.post(new Runnable())
  32.           handler.obtainMessage(1, "hello").sendToTarget();
  33.           //4、启动消息循环
  34.           Looper.loop();
  35.      }
  36. }).start();
复制代码
1

Java代码
  1. 1.public static final void prepare() {   
  2. 2.    if (sThreadLocal.get() != null) {  // 每个线程,只能有一个Looper对象   
  3. 3.        throw new RuntimeException("Only one Looper may be created per thread");   
  4. 4.    }   
  5. 5.    // 如果当前线程没有Looper,新建一个,构造函数是private的   
  6. 6.    sThreadLocal.set(new Looper());   
  7. 7.}   
  8. 8.private Looper() {   
  9. 9.    mQueue = new MessageQueue();   // 建立消息队列   
  10. 10.    mRun = true;   
  11. 11.    mThread = Thread.currentThread();   
  12. 12.}  
  13. public static final void prepare() {
  14.     if (sThreadLocal.get() != null) {  // 每个线程,只能有一个Looper对象
  15.         throw new RuntimeException("Only one Looper may be created per thread");
  16.     }
  17.     // 如果当前线程没有Looper,新建一个,构造函数是private的
  18.     sThreadLocal.set(new Looper());
  19. }
  20. private Looper() {
  21.     mQueue = new MessageQueue();   // 建立消息队列
  22.     mRun = true;
  23.     mThread = Thread.currentThread();
  24. }
复制代码
2

Java代码
  1. 1.public Handler(){   
  2. 2.    mLooper = Looper.myLooper(); // 取得当前线程的Looper,如果抛异常   
  3. 3.    if (mLooper == null) {   
  4. 4.        throw new RuntimeException(   
  5. 5.            "Can't create handler inside thread that has not called Looper.prepare()");   
  6. 6.    }   
  7. 7.    mQueue = mLooper.mQueue;  // 取得消息队列   
  8. 8.    mCallback = null;   
  9. 9.}  
  10. public Handler(){
  11.     mLooper = Looper.myLooper(); // 取得当前线程的Looper,如果抛异常
  12.     if (mLooper == null) {
  13.         throw new RuntimeException(
  14.             "Can't create handler inside thread that has not called Looper.prepare()");
  15.     }
  16.     mQueue = mLooper.mQueue;  // 取得消息队列
  17.     mCallback = null;
  18. }
复制代码
3

Java代码
  1. 1.//不管调用哪个方法,最终执行的是   
  2. 2.public boolean sendMessageAtTime(Message msg, long uptimeMillis){   
  3. 3.    boolean sent = false;   
  4. 4.    // 取得消息队列   
  5. 5.    MessageQueue queue = mQueue;   
  6. 6.    if (queue != null) {   
  7. 7.        msg.target = this;  // 消息发出着是自己   
  8. 8.        sent = queue.enqueueMessage(msg, uptimeMillis); // 添加到消息队列中   
  9. 9.    }   
  10. 10.    else {   
  11. 11.        RuntimeException e = new RuntimeException(   
  12. 12.            this + " sendMessageAtTime() called with no mQueue");   
  13. 13.        Log.w("Looper", e.getMessage(), e);   
  14. 14.    }   
  15. 15.    return sent;   
  16. 16.}   
  17. 17.final boolean enqueueMessage(Message msg, long when) {   
  18. 18.    if (msg.when != 0) {   
  19. 19.        throw new AndroidRuntimeException(msg   
  20. 20.                + " This message is already in use.");   
  21. 21.    }   
  22. 22.    if (msg.target == null && !mQuitAllowed) {   
  23. 23.        throw new RuntimeException("Main thread not allowed to quit");   
  24. 24.    }   
  25. 25.    synchronized (this) {   
  26. 26.        if (mQuiting) {   
  27. 27.            RuntimeException e = new RuntimeException(   
  28. 28.                msg.target + " sending message to a Handler on a dead thread");   
  29. 29.            Log.w("MessageQueue", e.getMessage(), e);   
  30. 30.            return false;   
  31. 31.        } else if (msg.target == null) {   
  32. 32.            mQuiting = true;   
  33. 33.        }   
  34. 34.  
  35. 35.        msg.when = when;   
  36. 36.        Message p = mMessages;   
  37. 37.        // 之前没有其他消息了,MessageQueue中当前消息mMessages 就是传递进来的msg   
  38. 38.        if (p == null || when == 0 || when < p.when) {   
  39. 39.            msg.next = p;   
  40. 40.            mMessages = msg;   
  41. 41.            this.notify(); // 唤醒   
  42. 42.        } else {   
  43. 43.            // 之前有其他消息了,将传递的msg放到适合的位置,根据when   
  44. 44.            Message prev = null;   
  45. 45.            while (p != null && p.when <= when) {   
  46. 46.                prev = p;   
  47. 47.                p = p.next;   
  48. 48.            }   
  49. 49.            msg.next = prev.next;   
  50. 50.            prev.next = msg;   
  51. 51.            this.notify();  // 唤醒   
  52. 52.        }   
  53. 53.    }   
  54. 54.    return true;   
  55. 55.}  
  56. //不管调用哪个方法,最终执行的是
  57. public boolean sendMessageAtTime(Message msg, long uptimeMillis){
  58.     boolean sent = false;
  59.     // 取得消息队列
  60.     MessageQueue queue = mQueue;
  61.     if (queue != null) {
  62.         msg.target = this;  // 消息发出着是自己
  63.         sent = queue.enqueueMessage(msg, uptimeMillis); // 添加到消息队列中
  64.     }
  65.     else {
  66.         RuntimeException e = new RuntimeException(
  67.             this + " sendMessageAtTime() called with no mQueue");
  68.         Log.w("Looper", e.getMessage(), e);
  69.     }
  70.     return sent;
  71. }
  72. final boolean enqueueMessage(Message msg, long when) {
  73.     if (msg.when != 0) {
  74.         throw new AndroidRuntimeException(msg
  75.                 + " This message is already in use.");
  76.     }
  77.     if (msg.target == null && !mQuitAllowed) {
  78.         throw new RuntimeException("Main thread not allowed to quit");
  79.     }
  80.     synchronized (this) {
  81.         if (mQuiting) {
  82.             RuntimeException e = new RuntimeException(
  83.                 msg.target + " sending message to a Handler on a dead thread");
  84.             Log.w("MessageQueue", e.getMessage(), e);
  85.             return false;
  86.         } else if (msg.target == null) {
  87.             mQuiting = true;
  88.         }

  89.         msg.when = when;
  90.         Message p = mMessages;
  91.         // 之前没有其他消息了,MessageQueue中当前消息mMessages 就是传递进来的msg
  92.         if (p == null || when == 0 || when < p.when) {
  93.             msg.next = p;
  94.             mMessages = msg;
  95.             this.notify(); // 唤醒
  96.         } else {
  97.             // 之前有其他消息了,将传递的msg放到适合的位置,根据when
  98.             Message prev = null;
  99.             while (p != null && p.when <= when) {
  100.                 prev = p;
  101.                 p = p.next;
  102.             }
  103.             msg.next = prev.next;
  104.             prev.next = msg;
  105.             this.notify();  // 唤醒
  106.         }
  107.     }
  108.     return true;
  109. }
复制代码
4

Java代码
  1. 1.public static final void loop() {   
  2. 2.    Looper me = myLooper();   
  3. 3.    MessageQueue queue = me.mQueue;   
  4. 4.    while (true) {                            // 死循环   
  5. 5.        Message msg = queue.next(); // 当队列中没有消息时会阻塞   
  6. 6.        if (msg != null) {   
  7. 7.            if (msg.target == null) {  // 消息没有发送者时,退出消息循环   
  8. 8.                // No target is a magic identifier for the quit message.   
  9. 9.                return;   
  10. 10.            }   
  11. 11.            if (me.mLogging!= null) me.mLogging.println(   
  12. 12.                    ">>>>> Dispatching to " + msg.target + " "  
  13. 13.                    + msg.callback + ": " + msg.what   
  14. 14.                    );   
  15. 15.            // 调用消息发出者的dispatchMessage,这里msg.target是我们sendMessage的handler   
  16. 16.            msg.target.dispatchMessage(msg);   
  17. 17.            if (me.mLogging!= null) me.mLogging.println(   
  18. 18.                    "<<<<< Finished to    " + msg.target + " "  
  19. 19.                    + msg.callback);   
  20. 20.            msg.recycle();   
  21. 21.        }   
  22. 22.    }   
  23. 23.}   
  24. 24.  
  25. 25.final Message next() {   
  26. 26.    boolean tryIdle = true;   
  27. 27.  
  28. 28.    while (true) {   
  29. 29.  
  30. 30.        synchronized (this) {   
  31. 31.            // 没有消息的或,会阻塞   
  32. 32.            try {   
  33. 33.                if (mMessages != null) {   
  34. 34.                    if (mMessages.when-now > 0) {   
  35. 35.                        Binder.flushPendingCommands();   
  36. 36.                        this.wait(mMessages.when-now);   
  37. 37.                    }   
  38. 38.                } else {   
  39. 39.                    Binder.flushPendingCommands();   
  40. 40.                    this.wait();   
  41. 41.                }   
  42. 42.            }   
  43. 43.            catch (InterruptedException e) {   
  44. 44.            }   
  45. 45.        }   
  46. 46.    }   
  47. 47.}  
  48. public static final void loop() {
  49.     Looper me = myLooper();
  50.     MessageQueue queue = me.mQueue;
  51.     while (true) {                            // 死循环
  52.         Message msg = queue.next(); // 当队列中没有消息时会阻塞
  53.         if (msg != null) {
  54.             if (msg.target == null) {  // 消息没有发送者时,退出消息循环
  55.                 // No target is a magic identifier for the quit message.
  56.                 return;
  57.             }
  58.             if (me.mLogging!= null) me.mLogging.println(
  59.                     ">>>>> Dispatching to " + msg.target + " "
  60.                     + msg.callback + ": " + msg.what
  61.                     );
  62.             // 调用消息发出者的dispatchMessage,这里msg.target是我们sendMessage的handler
  63.             msg.target.dispatchMessage(msg);
  64.             if (me.mLogging!= null) me.mLogging.println(
  65.                     "<<<<< Finished to    " + msg.target + " "
  66.                     + msg.callback);
  67.             msg.recycle();
  68.         }
  69.     }
  70. }

  71. final Message next() {
  72.     boolean tryIdle = true;

  73.     while (true) {

  74.         synchronized (this) {
  75.             // 没有消息的或,会阻塞
  76.             try {
  77.                 if (mMessages != null) {
  78.                     if (mMessages.when-now > 0) {
  79.                         Binder.flushPendingCommands();
  80.                         this.wait(mMessages.when-now);
  81.                     }
  82.                 } else {
  83.                     Binder.flushPendingCommands();
  84.                     this.wait();
  85.                 }
  86.             }
  87.             catch (InterruptedException e) {
  88.             }
  89.         }
  90.     }
  91. }
复制代码
总结
Handler作用:
1. 执行计划任务
2. 线程间通信

一个handler,只能接收到自己发出的message。handler实例与消息Message处理是关联的,发送和接受要匹配
Handler操作队列,主要是在子线程操作主线程的消息队列

Handler是实现异步的一种方式,用法是在主线程中建立Handler,(主线程中的Handler不用掉Looper.prepare);
在子线程(耗时操作)任务完成后sendMessage,这个Message会发送到主线程的消息队列中,主线程Handler的重写dispatchMessage方法,做新线程任务完成后的事情,大部分是更新UI。

1.png (14.02 KB, 下载次数: )

1.png
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP