一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第14天,点击查看活动详情。
d.dispatchMessage()
前面讲到,Looper在loop()时,从MessageQueue中取到消息时,会通过msg.target.dispatchMessage()来通知Handler来进行处理;
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
可以看到,在该方法内部会进行顺序判断来执行不同的消息处理逻辑:
1. callback是通过post(Runnable)方式中的Runnable[下面有解释],通过sendMessage时为null;
2. mCallback默认为null;
3. 调用子类的handleMessage方法,最终会调用本地实现的Handler中的handleMessage()来进行处理。
3.MessageQueue
MessageQueue的主要方法有enqueueMessage():将消息添加到queue里;next():不断的取出message;quit():退出消息循环,继而退出Looper.loop()。
a.enqueueMessage()
boolean enqueueMessage(Message msg, long when) {
......
//----------------分析点1------------------------
synchronized (this) {
......
msg.markInUse();
msg.when = when;
Message p = mMessages;
boolean needWake;
//----------------分析点2------------------------
if (p == null || when == 0 || when < p.when) {
// New head, wake up the event queue if blocked.
msg.next = p;
mMessages = msg;
needWake = mBlocked;
} else {
// Inserted within the middle of the queue. Usually we don't have to wake
// up the event queue unless there is a barrier at the head of the queue
// and the message is the earliest asynchronous message in the queue.
needWake = mBlocked && p.target == null && msg.isAsynchronous();
Message prev;
//-------------------分析点3---------------------------
for (;;) {
prev = p;
p = p.next;
if (p == null || when < p.when) {
break;
}
if (needWake && p.isAsynchronous()) {
needWake = false;
}
}
msg.next = p; // invariant: p == prev.next
prev.next = msg;
}
// We can assume mPtr != 0 because mQuitting is false.
//-------------------分析点4---------------------------
if (needWake) {
nativeWake(mPtr);
}
}
return true;
}
从上面代码可以看到,主要的点为:
分析点1:加入synchronized (this)是防止多个Handler同时往queue中插入消息,出现混乱的场景。
分析点2:消息的queue中没有消息或message需要立刻执行(when=0)或当前message执行时间小于queue里面所有消息的最早执行时间时,就把当前message插于queue的头部,然后执行nativeWake()唤醒next(),然后将message最早给loop()执行;
分析点3:当不满足以上3个条件时,则需要把当前消息根据执行时间(when)插入到queue中的合适位置,此时不需要执行nativeWake()唤醒next(),因为不执行当前消息;
分析点4:是否需要唤醒next(),来按顺序执行消息;