本文是介绍 HandlerThread 这个类的使用以及源码分析,单从这个类的名称上看,我们就知道这个类可能会和 Handler 和 Thread 有关系。
进入正题以前,我们先来看一下 Handler、Thread 和 Looper 的关系。
Handler、Thread 和 Looper 的关系
Looper类别用来为一个线程开启一个消息循环。默认情况下 Android 中新诞生的线程是没有开启消息循环的。(主线程除外,主线程系统会自动为其创建Looper对象,开启消息循环)。Looper对象通过MessageQueue来存放消息和事件。一个线程只能有一个Looper,对应一个MessageQueue。
通常是通过Handler对象来与Looper交互的。Handler可看做是Looper的一个接口,用来向指定的Looper发送消息及定义处理方法。- 默认情况下
Handler会与其被定义时所在线程的Looper绑定,比如,在主线程中定义,其是与主线程的Looper绑定。mainHandler = new Handler()等价于new Handler(Looper.myLooper())Looper.myLooper()用来获取当前进程的Looper对象。
还有一个类似的Looper.getMainLooper()用于获取主线程的Looper对象。 在非主线程中直接
new Handler()会报如下的错误:1
java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
原因是非主线程中默认没有创建
Looper对象,需要先调用Looper.prepare()启用Looper。- 需要先调用
Looper.prepare()启用Looper。
调用Looper.loop()让Looper开始工作,从消息队列里取消息,处理消息。
注意:写在Looper.loop()之后的代码不会被执行,这个函数内部应该是一个循环,当调用mHandler.getLooper().quit()后,loop 才会中止,其后的代码才能得以运行。
Handler和Thread结合
了解了上面的知识,如果我们想在一个子线程里面处理消息,就需要实现下面的代码:
1 | class LooperThread extends Thread { |
可以看到实现起来比较麻烦。
那么在这种情况下,HandlerThread 应运而生。
HandlerThread 的用法
HandlerThread 是一个包含 Looper 的 Thread,我们可以直接使用这个 Looper 创建 Handler。
1 | private HandlerThread mUpdateStatusThread; |
HandlerThread 相当于给 Handler 提供了一个 Looper,那么多个 Handler 共用一个 HandlerThread,显然也是可以的。
比如我们需要在后台处理多中任务,可能需要建多个 Handler(当然在一个 Handler 处理也是可行的),那么我们就可以只创建一个 HandlerThread,多个 Handler 通过 HandlerThread.getLooper() 来获取 Looper 对象来创建 Handler。
1 | public class LooperUtils { |
1 | mUpdateStatusHandler = new UpdateStatusHandler(LooperUtils.getThreadLooper(), this); |
源码分析
1 | public class HandlerThread extends Thread { |