一、内容概览
说到Android中的消息机制,你会想到什么,Handler? Message?没错在开发中确实是是handler和Message用的最多了,最常见的就是子线程通知UI线程更新UI。但是Android中的消息机制并不仅仅这么简单,我们从以下几点开始分析:
- 消息机制概述
- MessageQueue的原理
- Looper的工作原理
- Handler的工作原理
二、消息机制概述
消息机制主要包含:MessageQueue,Handler和Looper这三大部分,以及Message,下面我们一一介绍。
Message:需要传递的消息,可以传递数据;
MessageQueue:消息队列,但是它的内部实现并不是用的队列,实际上是通过一个单链表的数据结构来维护消息列表,因为单链表在插入和删除上比较有优势。主要功能向消息池投递消息(MessageQueue.enqueueMessage)和取走消息池的消息(MessageQueue.next);
Handler:消息辅助类,主要功能向消息池发送各种消息事件(Handler.sendMessage)和处理相应消息事件(Handler.handleMessage);
Looper:不断循环执行(Looper.loop),从MessageQueue中读取消息,按分发机制将消息分发给目标处理者。
下面给出一张来自网络的消息机制的流程图:

三、MessageQueue的原理
MessageQueue主要包含两个操作,插入和读取,而读取也是伴随着删除操作,插入和读取对应的方法是enqueueMessage和next,都说源码是最好的书籍,直接看源码:
1 | boolean enqueueMessage(Message msg, long when) { |
MessageQueue是按照Message触发时间的先后顺序排列的,队头的消息是将要最早触发的消息。当有消息需要加入消息队列时,会从队列头开始遍历,直到找到消息应该插入的合适位置,以保证所有消息的时间顺序。
1 | Message next() { |
nativePollOnce是阻塞操作,其中nextPollTimeoutMillis代表下一个消息到来前,还需要等待的时长;当nextPollTimeoutMillis = -1时,表示消息队列中无消息,会一直等待下去。
可以看出next()方法根据消息的触发时间,获取下一条需要执行的消息,队列中消息为空时,则会进行阻塞操作。
说完了MessageQueue的两个方法后,那到底这两个方法是谁在调用呢?Looper和Handler就应该上场了
四、Looper的工作原理
就是Looper在调用MessageQueue中的next的,到底怎么调用的呢,我们接着看,首先要创建一个looper:
初始化Looper
无参情况下,默认调用prepare(true);表示的是这个Looper可以退出,而对于false的情况则表示当前Looper不可以退出。。
1 | public static void prepare() { |
这里看出,不能重复创建Looper,只能创建一个。创建Looper,并保存在TheadLocal中。
开启Looper
1 | public static void loop() { |
loop()进入循环模式,不断调用queue的next方法,直到消息为空时退出循环,拿到message后,在通过msg.target.dispatchMessage把Message分发给相应的target,这里的target其实就是我们接下来要讲的Handler。
五、Handler的工作原理
Handler的工作主要包含消息的发送和接收。消息的发送都是通过send和post的一系列方法来实现的,其实最终调用的都是sendMessageAtTime
1 | public boolean sendMessageAtTime(Message msg, long uptimeMillis) { |
可以看到sendMessageAtTime()`方法的作用很简单,就是调用MessageQueue的enqueueMessage()方法,往消息队列中添加一个消息。MessageQueue的next方法会返回这条消息给Looper,Looper收到消息后分发给Handler处理,即Handler的dispatchMessage方法会被调用:
1 | public void dispatchMessage(Message msg) { |
可以看到消息的处理很简单,我们都知道handleMeaage()是我们经常实例化一个handler对象的时候需要重写的方法,msg.callback是调用post系列方法传过来的runnable对象,那mCallback是个什么鬼?
Callback是个接口,定义如下:
1 | public interface Callback { |
通过Callback可以创建Handler对象:Handler handler = new Handler(callback);看到这里我们就明白了,如果我们不想派生一个Handler子类的话,就可以用这种方式新建Handler对象
这里有个需要注意的地方,在Activity退出的时候,记得调用下removeCallbacksAndMessages(null),移除掉所有的callback和message,防止内存泄漏。
六、总结
总结的话再次盗用网上的一张图,毕竟图形化的东西更容易理解。

最后感谢《Android开发艺术探索》这本书的作者玉刚!