[Framework] Android Handler 工作原理
Android 中的 Handler
都被人说烂了,但是还是想多说一次,因为在 Android 的系统中它真的非常重要而且它的机制并没有很复杂,无论是新手和老手都可以好好学习下,这对理解 Android 系统很重要,所以说学习的性价比非常高。
Android 中 IPC
跨进程通信主要依靠 Binder
(参考我之前的文章 Android Binder 工作原理), 而同一个进程的通信就主要依靠 Handler
。
这里先简单描述下 Handler
的工作流程:
首先在 Handler
处理任务的线程需要调用 Looper#prepare()
方法,来为当前线程创建一个 Looper
实例,这个实例通过 ThreadLocal
存放,也就是一个线程只能有一个这个实例;Looper
构造函数中会初始化一个 MessageQueue
对象,MessageQueue
对象就是用来封装任务的队列,它是用的链表实现,而任务队列的 Item 就是 Message
对象,也就是单个的任务;任务处理线程调用 Looper#prepare()
方法完成后,会调用 Looper#loop()
方法,这个时候任务线程就会阻塞去处理对应 Looper
中的 MessageQueue
中的任务,处理的方式就是一个死循环从 MessageQueue
中去获取最新的 Message
获取到后,然后调用对应的 Handler#handleMessage()
方法去执行它,执行完成后又去获取下一个任务,如果没有新的任务就会陷入阻塞,等有新的任务来的时候会唤醒这个阻塞(这个唤醒机制是用的 Linux 中的 epoll
机制),继续执行新的任务。
上面大致描述了 Looper
和 MessageQueue
如何从队列中获取新的任务和执行任务,这里再简单描述下怎么插入任务,首先要自定一个 Handler
对象,构造函数中需要传入上面所创建的 Looper
对象,其中自定义的 Handler#handleMessage
方法就是用来执行任务的方法,其他的线程需要向对应的 Looper
线程添加任务时,就调用上面 Handler
实例的 sendMessage
方法来添加任务,也就是向 MessageQueue
队列中添加任务,最终会在 Looper
所对应的线程执行,这样就完成了一次跨线程的通信。
下面是一个简单的 Handler
使用的代码:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
var handlerLooper: Looper? = null
val handlerThread = object : Thread() {
override fun run() {
super.run()
Looper.prepare()
handlerLooper = Looper.myLooper()
Looper.loop()
}
}
handlerThread.start()
while (handlerLooper == null) {
// 等待 HandlerThread 初始化完成
}
val handler = object : Handler(handlerLooper!!) {
override fun handleMessage(msg: Message) {
super.handleMessage(msg)
if (msg.what == 0) {
// TODO: 处理任务,该方法最终工作在 HandlerThread 线程
}
}
}
val msg = handler.obtainMessage(0)
// 发送的代码工作在主线程
handler.sendMessage(msg)
}
Android 中有现成的 HandlerThread
,不用自定义,我这里是为了展示这个过程。
Tips: 我后续的源码分析都是基于 andorid 31
Looper
Looper 初始化
// ...
public static void prepare() {
prepare(true);
}
private static void prepare(boolean quitAllowed) {
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
sThreadLocal.set(new Looper(quitAllowed));
}
// ...
// ...
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);
mThread = Thread.currentThread();
}
// ...
初始化的过程非常简单,如果当前线程已经有 Looper
对象就直接报错,如果没有新建一个 Looper
对象放在 ThreadLocal
中,在 Looper
的构造函数中,创建了 MessageQueue
实例和保存了当前的 Thread
对象。
Looper 任务处理
// ...
public static void loop() {
final Looper me = myLooper();
if (me == null) {
throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
}
if (me.mInLoop) {
Slog.w(TAG, "Loop again would have the queued messages be executed"
+ " before this one completed.");
}
me.mInLoop = true;
// ..
me.mSlowDeliveryDetected = false;
for (;;) {
if (!loopOnce(me, ident, thresholdOverride)) {
return;
}
}
}
// ...
Looper#loop()
方法也非常简单,修改了当前的 Looper
的一些状态,然后在死循环中无限调用 loopOnce()
方法去执行任务,如果该方法返回 false
就表示该 Looper
已经退出,就跳出循环。
private static boolean loopOnce(final Looper me,
final long ident, final int thresholdOverride) {
Message msg = me.mQueue.next(); // might block
if (msg == null) {
// No message indicates that the message queue is quitting.
return false;
}
// This must be in a local variable, in case a UI event sets the logger
final Printer logging = me.mLogging;
if (logging != null) {
logging.println(">>>>> Dispatching to " + msg.target + " "
+ msg.callback + ": " + msg.what);
}
// ...
Object token = null;
if (observer != null) {
token = observer.messageDispatchStarting();
}
long origWorkSource = ThreadLocalWorkSource.setUid(msg.workSourceUid);
try {
msg.target.dispatchMessage(msg);
if (observer != null) {
observer.messageDispatched(token, msg);
}
dispatchEnd = needEndTime ? SystemClock.uptimeMillis() : 0;
} catch (Exception exception) {
if (observer != null) {
observer.dispatchingThrewException(token, msg, exception);
}
throw exception;
} finally {
ThreadLocalWorkSource.restore(origWorkSource);
if (traceTag != 0) {
Trace.traceEnd(traceTag);
}
}
if (logging != null) {
logging.println("