基于 Android 7.1.1 源码,分析 handler 的架构和原理。
0 前言
本片博客通过以下几个方面总结 Handler 源码的实现架构!
1 create Handler
Handler 提供了如下的构造器方法:
1 | //【方法1】默认使用当前的线程的 Looper 对象创建 Handler,如果当前线程的没有 Looper,那就会抛出异常! |
Handler 默认是同步的,如果我们显式的设置 async 为 true,那么其该 handler 会以异步的方式处理 message 和 runnable!
关于异步的实现,我们后续会分析!
其中,最核心的构造方法是方法 6 和方法 7,其他方法都是调用它们完成初始化的:
1.1 Handler(Callback, boolean)
默认使用当前线程的 Looper 对象:
1 | public Handler(Callback callback, boolean async) { |
1.2 Handler(Looper,Callback, boolean)
显示指定了 Looper 对象!
1 | public Handler(Looper looper, Callback callback, boolean async) { |
1.2 成员变量
构造器中出现了 Handler 的主要成员变量,下面解释一下,也便于后续分析:
1 | final Looper mLooper; |
Looper 对象;
1 | final MessageQueue mQueue; |
消息队列,来自 Looper 对象;
1 | final Callback mCallback; |
Callback 回调,该回调会被封装成 message;
1 | final boolean mAsynchronous; |
该 handler 是否是异步的,默认为 false;
2 Handler.obtainMessage
Handler 提供了多个 obtainMessage 方法,来复用一个 Message 对象!
1 | public final Message obtainMessage() {...} |
Handler 允许我们复用 Message 对象,这样可以避免过多的创建 Message 对象!
Message 有一个静态变量 Message sPool 他是一个消息池链表的头元素,obtainMessage 会从该消息池中复用 Message,并用参数初始化复用的 Message!
obtainMessage 方法最终会调用 Message.obtain 方法:
1 | public final Message obtainMessage(int what, int arg1, int arg2) { |
关于 Message.obtain,我们后面会分析,这里我们只需要知道,复用的时候,会从消息池链表的头元素开始,复用消息!
3 Handler.sendMessage
Handler 提供了多个 sendMessage 方法,来发送一个 Message 对象!
1 | public final boolean sendMessage(Message msg) {...} |
通过这些方法我们可以实现立即或者延迟发送消息!
如果指定的是延迟时间,那么会通过 SystemClock.uptimeMillis() + delayMillis 方式计算为绝对时间!
sendMessage 最后调用的是 Handler.enqueueMessage,就是将 Message 插入到消息队列中!!
3.1 Handler.enqueueMessage
我们来看看 enqueueMessage 方法:1
2
3
4
5
6
7private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
msg.target = this;
if (mAsynchronous) { // 如果 Handler 是异步的,那么 Message 也是异步的!
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis);
}
通过 MessageQueue.enqueueMessage 方法,将消息压入到消息队列中!
如果 uptimeMillis 为 0 ,会将消息插入到消息队列的头部;如果 uptimeMillis 不为 0 ,会按照 uptimeMillis 将消息插入到消息队列的指定位置;
4 Handler.post
Handler 除了可以发送消息,进行线程间通信,还可以执行指定的任务 Runnable,Handler 提供了多个 post 方法供我们选择:
1 | public final boolean post(Runnable r) {...} |
通过这些方法我们可以实现立即或者延迟执行任务!
Runnable 的执行很有意思:
1 | public final boolean post(Runnable r){ |
我们去看看 getPostMessage() 方法:
4.1 Handler.getPostMessage
getPostMessage 用于将 Runnable 封装为 Message!
1 | private static Message getPostMessage(Runnable r) { |
优先复用消息池中的消息!
5 Handler.dispatchMessage
回顾 Loop.loop() 方法,当 queue.next() 能够返回一个可以分发的 Message 后,会调用下面的逻辑,处理消息!
1 | try { |
这里的 msg.target 就是目标 Handler:
1 | public void dispatchMessage(Message msg) { |
对于 Runable 来说,虽然其被封装为了 Message,但是由于其 what 的特殊性,无法按照一般的 Message 的去处理,
5.1 Handler.handleCallback
对于 Runable,通过 handleCallback 方法处理,该方法会调用 Runnable.run() 方法来执行任务!
1 | private static void handleCallback(Message message) { |
不多说了!
5.2 Callback.handleMessage
对于 Message,如果我们指定了回调接口 Callback,那就通过 Callback 处理 Message:1
2
3public interface Callback {
public boolean handleMessage(Message msg);
}
mCallback 为 Handler 的成员变量,需要显式指定!
Callback 是 Handler 的内部接口!
5.3 Handler.handleMessage
对于 Message,默认使用 Handler 的 handleMessage 来处理:
1 | public void handleMessage(Message msg) { |
我们需要复写该方法,实现自己的逻辑!!
6 handler.removeMessages
同时 Handler 也提供了移除消息的操作;1
2
3
4
5public final void removeMessages(int what) {...}
public final void removeMessages(int what, Object object) {...}
public final void removeCallbacksAndMessages(Object token) {...}
最终调用的是 MessageQueue 的 remove 方法;
1 | mQueue.removeMessages(this, what, object); |
MessageQueue 的 remove 操作的原理很简单,根据输入的参数,进行匹配即可!!
7 跨进程通信
Handler 也可以用于跨进程通信:Messenger
Handler 有一个变量 IMessenger mMessenger 用于保存通过 Messenger 跨进程通信是服务端的桩对象!
1 | final IMessenger getIMessenger() { |
Messenger 信使本质上实现了 Aidl 模板,下面是服务端桩的实现!
1 | private final class MessengerImpl extends IMessenger.Stub { |
跨进程的分析会在单独的文章中,这里不再过多的介绍!!
8 其他方法
- 判断消息队列中是否有指定的消息!
1 | public final boolean hasMessages(int what, Object object) { |