理解 Handler 框架
本篇我们先从 HandlerThread 讲起,然后整体上看看 Handler 框架。
从 HandlerThread 谈起
HandlerThread 是 Android API 的一部分,目的是让我们更方便地在工作线程使用 Handler 框架,它的实现并不是很复杂,我们直接看代码:
1  | // frameworks/base/core/java/android/os/HandlerThread.java  | 
如果想在工作线程中使用 Handler 框架,关键的动作只有两个:
- 执行 
Looper.prepare()对Looper进行初始化 Looper.loop()开始事件循环。
上面代码段中间的 synchronized 块,需要结合 getLooper() 来看:
1  | // frameworks/base/core/java/android/os/HandlerThread.java  | 
创建了一个基于 Handler 框架的线程后,我们需要通过 Handler 把任务 post 到工作线程。为了拿到这个 Handler,有两个方法可以选择:
- 继承 
HandlerThread并重写onLooperPrepared()方法。在这个方法中,可以直接创建Handler(这个方法运行在工作线程,而使用Handler的一般是这个工作线程之外的其他线程,需要注意Handler实例的可见性)。 - 创建 
HandlerThread后,调用handlerThread.getLooper()拿到对应的Looper,接着new Handler(looper)。 
我们重点关注第二种方法。它的问题在于,getLooper 的时候,对应的 Looper 可能还没有初始化。这种情况下,调用线程就需要等待,直到 Looper 完成初始化。
在 getLooper() 中,如果 mLooper == null,说明还有初始化,调用 wait() 开始等待。而在 run() 中,初始化完成后调用 notifyAll() 唤醒所有等待线程(可能不止一个线程在等待)。
Handler 框架的使用就讲到这里,下面我们看看它的实现。
框架概览
总的来说,就是 Looper 不断地从 MessageQueue 里拿出 Message 执行。而 Message 是通过 Handler 插入 MessageQueue 的。
Looper 的构造
首先我们看看 Looper.prepare():
1  | //frameworks/base/core/java/android/os/Looper.java  | 
prepare() 方法做的事很简单,就是创建一个 Looper 实例,然后放到 sThreadLocal 中。普通的 Looper 是允许退出的,而主线程则不行:
1  | //frameworks/base/core/java/android/os/Looper.java  | 
在它的构造函数,则创建了一个 MessageQueue:
1  | //frameworks/base/core/java/android/os/Looper.java  | 
Looper 中的循环
执行 Looper.prepare() 后,就可以使用 Looper.loop() 开始事件循环:
1  | //frameworks/base/core/java/android/os/Looper.java  | 
Looper.loop() 所做的,就是在一个循环中,不断地从 MessageQueue 取出 Message 并执行。
我们先看看 msg.target.dispatchMessage(msg), msg.target 就是 Handler:
1  | //frameworks/base/core/java/android/os/Handler.java  | 
- 如果 
Message中的Runnable(这里的msg.callback) 不为空,就执行runnable.run() - 如果 
mCallback不为空,就给mCallback处理。mCallback通过构造函数设置 - 以上两个都不成立,调用自身的 
handleMessage()处理,子类可以重写handleMessage() 
现在我们看 msg.recycleUnchecked()。从字面意思看,应该是回收这个 Message:
1  | //frameworks/base/core/java/android/os/Message.java  | 
果然,recycleUnchecked 将自己(Message 对象)放在了以 sPool 为头结点的列表中。缓存的对象可以使用 Message.obtain() 再拿出来使用:
1  | //frameworks/base/core/java/android/os/Message.java  | 
Looper 的退出
前面我们看到,Looper.loop() 里面有一个无限循环,默认情况下,他永远不会退出。但是,某些时候,我们还是希望对应的线程能够终止,以回收一些资源。
需要 Looper 退出时,执行 Looper.quit() 即可:
1  | //frameworks/base/core/java/android/os/Looper.java  | 
quit() 执行后,会清空 MessageQueue 中剩余的未执行的 message,然后唤醒在 MessageQueue 上等待的线程。线程醒来后,next() 方法将会返回 null,于是,Looper.loop() 就返回了。
1  | //frameworks/base/core/java/android/os/Looper.java  | 
Handler 的使用
最后,我们看看 Handler。这里我们只分析带 Looper 参数的构造函数版本,实现上很简单:
1  | //frameworks/base/core/java/android/os/Handler.java  | 
我们通过 handler 向 looper 线程发送 Message 后,最终会到达 sendMessageAtTime 方法:
1  | public boolean sendMessageAtTime(Message msg, long uptimeMillis) {  | 
这里可以看到,handler 通过 queue.enqueueMessage() 将 Message 放到了 MessageQueue 中。并且,把 msg.target 设置为自己。还记得吗:在 Looper 中有这么一行代码:
1  | //frameworks/base/core/java/android/os/Looper.java  | 
Looper.loop() 中使用的 msg.target 就是在 Handler 里面设置的,这样一来,某个 handler 实例发送的 message,最终也会由自己处理。
Handler 框架到这里,基本就讲清楚了。如果你还有什么不明白的地方,最好自己对照着源码看一遍。如果看过几遍源码还不理解,可以发邮件跟我一起讨论。