Handler Looper Message源码研究

Looper是消费者,Handler是生产者(同时Looper消费后,也会通知Handler),MessageQueue是消息队列,队列的实现方式是链表,Message是链表的一个节点。 我们的程序基本上之和Handler打交道。

线程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即sendMessage,又handlerMessage,事情还是只有一个线程在做事情。
但是后来想想,明白了这样设计的必要性。
因为这个唯一的线程一般而言,都是mainUI线程,如果你有个可以分成多个小任务的任务要处理,你没有使用Handler,直接执行,也许系统忙于处理你这个任务,而无法及时响应用户事件,从而导致ANR的抛出。
如果你把你的任务拆成几个小任务,用Handler来实现,那么系统就可以把你的小任务推到后面来处理,抽出时间来响应用户操作。
如果真的有大任务,一般式需要另外线程去处理,或者开启Service。




一个在新线程中使用handler例子,我们来分析下源码
Java代码   收藏代码
  1. new Thread(new Runnable() {  
  2.      @Override public void run() {  
  3.           Handler handler;  
  4.           //1、初始化Looper  
  5.           Looper.prepare();  
  6.           //2、绑定handler到CustomThread实例的Looper对象、定义处理消息的方法  
  7.           handler= new Handler() {  
  8.                @Override public void handleMessage(Message msg) {  
  9.                }  
  10.           };  
  11.           // 3、发送消息  
  12.           handler.sendMessage(new Message());  
  13.           handler.post(new Runnable())  
  14.           handler.obtainMessage(1"hello").sendToTarget();  
  15.           //4、启动消息循环  
  16.           Looper.loop();  
  17.      }  
  18. }).start();  


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


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


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


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


总结
Handler作用:
1. 执行计划任务
2. 线程间通信

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

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值