前言
首先我们要知道,创建Handler之前,要先创建与之配套的Looper。
在主线程中,系统已经初始化了一个 Looper 对象,因此程序直接创建 Handler 对象即可,然后就可以通过 Handler 来发送、处理消息了。
在子线程中,必须自己创建一个 Looper 对象,并启动它。
创建 Looper 对象调用它的 prepare 方法即可(prepare 方法保证每个线程最多只有一个 Looper 对象),然后调用 Looper 的静态 loop 方法来启动它。loop 方法使用一个死循环不断地从MessageQueue 中取消息,并将取出的消息分发给该消息对应的 Handler 处理。至于它们具体做了哪些事,我们会在后面详细讲述。
Looper的创建
我们先看一下Looper的构造函数
1 | private Looper(boolean quitAllowed) { |
首先我们注意到该构造方法是被private修饰的,也就是说我们无法通过new
的方式来创建Looper。其次,我们可以从Looper的构造方法中看出,在创建Looper的时候,创建了与之配套的MessageQueue,然后获取了创建当前Looper线程的引用。
而要想创建Looper,只需调用Looper.prepare();
。该方法保证了一个线程只能创建一个与之相关联的Looper,并且将创建出的Looper与当前线程绑定起来。
1 | public static void prepare() { |
Handler的创建
Looper对象成功创建之后,我们再来看看Handler。当我们调用Handler的无参构造函数创建Handler时,它内部调用了另一个重载的构造方法this(null, false)
。
1 | public Handler(Callback callback, boolean async) { |
从构造方法中,我们可以看出,handler获取了与当前线程相关联的Looper及MessageQueue的引用。
Handler 发送消息
创建完Handler之后,我们先从handler.sendMessage()
说起:
1 | public class MainActivity extends Activity{ |
而不管我们调用sendEmptyMessage()
或者是sendMessage()
,最终都会走到这里:
1 | public boolean sendMessageAtTime(Message msg, long uptimeMillis) { |
关键是最后return时,调用了enqueueMessage()
,我们一起看一下该方法的具体实现:
1 | private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) { |
从enqueueMessage
的方法实现可以看出,要发送的消息获取到了当前Handler的引用,也就是msg.target
。然后这条信息被加入到了与当前线程相关联的MessageQueue中。到此,发送消息的逻辑已经结束。
那么Handler处理消息的方法又是在什么时候回调的呢?要弄明白这一点,我们要对Looper.loop()
进行分析。
Looper.loop();
前面我们也已经提过,要创建一个Handler其实是需要三个步骤的:
- 调用
Looper.prepare();
- 创建Handler
- 调用
Looper.loop();
前面两步我们已经讲解过了,那你肯定会好奇,loop()
中到底做了什么呢?我们一起来看一下。
1 | public static void loop() { |
从源码可以看出,loop()
其实调用了一个死循环,不断的从与Looper配套的MessageQueue中取消息,然后调用msg.target.dispatchMessage(msg);
进行消息的分发。
前面Handler发送消息的时候,我们已经分析过,每个要发送的Message都获取到了发送它的Handler的引用,也就是msg.target
。因此这里msg.target.dispatchMessage(msg);
其实也就是调用了handler的dispatchMessage
进行消息的分发。
Handler的handleMessage()何时被回调?
我们一起来看一下handler的dispatchMessage()
:
1 | public void dispatchMessage(Message msg) { |
很明显,就是在这里,Handler的handleMessage
被回调了。
综上,我们可以说,是在Looper.loop()
中,当循环不断的从MessageQueue中获取消息时,间接调用了Handler的handleMessage()
方法。