一、从构造函数开始
可以看到,Handler的构造函数里,关联了Looper(通过Looper.myLooper()方式取得)、Queue(MessageQueue,从Looper中取得)、Callback()、async.
接下来,看一下 Looper.myLooper():
myLooper()取得的Looper是存储在ThreadLocal中的。通过looper.prepare()初始化并存储:
通过方法,可以看到,prepare()函数只能被调用一次,不然会throw Exception。这样可以保证,一个ThreadLocal中只存在一个Looper。
再看Looper的构造函数:
在looper的构造方法里,主要做了两件事:
1、创建一个looper管理的消息队messageQueue;
2、获得当前的线程;
到这里,Handler的构造函数,基本流程跑完。总结一下,new 一个handler的时候,会得到一个绑定在ThreadLocal中的Looper实例、一个与Looper绑定的MessageQueue实例,这三个实例对象互相绑定,从而进行信息交流。
二、信息发送流程。
handler通过sendMessage()、sendMessageDelayed()、sendMessageAtTime()等方法发送信息,最终这些方法都会走入同一个方法:enqueueMessage()
在enqueueMessage()方法中,先是将本handler对象赋值msg.target.之后执行了messageQueue的消息队列插入消息操作MessageQueue.enqueueMessage():
此函数执行的是单链表的插入操作,从此也可以看出。MessageQueue实际上是由单链表实现的。
三、消息处理流程。
将Message插入MessageQueue之后,我们知道。与MessageQueue绑定的Looper会调用 loop()方法一直循环遍历MessageQueue:
清晰明了,获取当前looper和与其对应的MessageQueue。通过一个for(;;)死循环,从MessageQueue中遍历获取Message。这边注意,messageQueue.next()方法中如果没有Message,会在next()方法中block住,直到有Message被enQueue入MessageQueue队列中,next()方法继续执行,loop()也可以瞬间得到Message。而只有在looper调用quit()或quitSafely()方法,messageQueue的next()方法才会返回null(此时MessageQueue同样调用了quit()方法),此时loop的无限循环也将结束。
looper.quit()和looper.quitSafely()的区别是:quit()直接退出Looper,quitSafely()只是设置一个退出标志,等消息队列中的消息处理完毕,就会退出Looper,这时候Handler的send方法返回false。如果在子线程中手动创建了Looper,要记得退出Looper,不然这个线程会一直处于等待转态,如果退出了,这个线程也会被终止。
接下来,我们来看一下 MessageQueue的next()方法:
就像我们之前说的那样,如果单向链表中有Message,便取出这个Message return出去,如果链表中已经没有Message,便通过Binder.flushPendingCommands() block当前操作。
回到Looper.loop()中,当looper从MessageQueue中得到Message之后,便会调用msg.target.dispatchMessage(msg)去处理Message。之前我们提到过,在Handler发送消息的enqueueMessage()方法中,已经将当前Handler赋值给了msg.target.此时,便是将发送message的handler变量取出,调用其dispatchMessage(msg)方法处理Message。
Handler的消息处理过程如下:
首先先检查Message的callback是否为空,不为空就通过handleCallback来处理,Message的callback是一个Runnable对象,实际上就是Handler的post方法所传递的Runnable参数
其次检查mCallback是否为null,不为null就调用mCallback的handleMessage方法来处理,Callback是个接口,定义如下:
public interface Callback {
public boolean handleMessage(Message msg);
}
通过Callback可以采用如下方法创建Handler handler = new Handler(callable)。在日常开发中,创建Handler最常见的方式是派生一个Handler的子类并且重写它的handleMessage方法,另外一种是传入一个Callback,并实现callback的handleMessage方法。
最后调用Handler的handleMessage方法来处理消息。
处理过程的流程图:
四、Handler使用注意事项
1、创建massage对象时,推荐使用obtain()方法获取,因为Message内部会维护一个Message池用于Message的复用,这样就可以避免 重新new message而冲内心分配内存,减少new 对象产生的资源的消耗。
2、handler 的handleMessage方法内部如果有调用外部activity或者fragment的对象,一定要用弱饮用,handler最好定义成static的,这样可以避免内存泄漏;为什么呢?因为一但handler发送了消息。而handler内部有对外部变量的引用,此时handler已经进入了looper的messageQueue里面。此时activity或者fragment退出了可是区域,但是handler内部持有其引用且为强引用时,其就不会立即销毁,产生延迟销毁的情况。