08. Carson Handler总结的机制源码解析
2022年4月16日
08. Carson Handler总结的机制源码解析
在阅读一次源码后模糊不懂的点,解析及影响加深
消息的处理
一.Handler是如何绑定当前线程的?
Handler初始化的时候,做了2件事
1. 指定Looper对象。
Looper对象的获取来自LocalThread.get(). Looper对象的创建来自于Looper.prepare(),使用ThreadLocal.set(new Looper()). 而ThreadLocal将Looper对象与当前线程绑定。
ThreadLocal
ThreadLocal 实例通常是希望将状态与线程相关联的类中的私有静态字段
2. 绑定MessageQueue
Handler的MessageQueue来自Looper.mQueue。而Looper.mQueue在 Looper对象创建时初始化。
总结
Handler初始化的时候从ThreadLocal,将Looper实例与线程关联,持有Looper中的MessageQueue对象的引用。所以从子线程发送的消息,可以通过MessageQueue获取Messager到looper,并使用 msg.target.dispatchMessage(msg)分发消息。
二.MessageQueue是如何将消息出队的
按照Messager对象的创建时间顺序出队。
三.Handler.dispatchMessage
1. Handler.handleCallback()
回调Runnable对象里复写的run()
2. Handler.handleMessage
复写子类handleMessage方法
消息的发送
1. 使用Message.target.dispatchMessage() 中target,Message是什么时候持有Handler引用的
Handler.enqueueMessage中,将当前Handler实例作为message的target属性。
2. enqueueMessage 消息入队
消息队列里,无消息就插入队头,有消息就按照Message入队时间插入到队列中。
之后随着Looper对象的无限循环消息,不断从消息队列中取出消息,分发到对应的handler
boolean enqueueMessage(Message msg, long when) {
...// 仅贴出关键代码
synchronized (this) {
msg.markInUse();
msg.when = when;
Message p = mMessages;
boolean needWake;
// 判断消息队列里有无消息
// a. 若无,则将当前插入的消息 作为队头 & 若此时消息队列处于等待状态,则唤醒
if (p == null || when == 0 || when < p.when) {
msg.next = p;
mMessages = msg;
needWake = mBlocked;
} else {
needWake = mBlocked && p.target == null && msg.isAsynchronous();
Message prev;
// b. 判断消息队列里有消息,则根据 消息(Message)创建的时间 插入到队列中
for (;;) {
prev = p;
p = p.next;
if (p == null || when < p.when) {
break;
}
if (needWake && p.isAsynchronous()) {
needWake = false;
}
}
msg.next = p;
prev.next = msg;
}
if (needWake) {
nativeWake(mPtr);
}
}
return true;
}
post
内部根据Runnable对象而封装。 实际上是创建Messager对象,让Messager持有callback,然后在dispatchMessage的时候调用messager.callback.run();