1. Handler通过sent或者post方法将目标Message推送至MessageQueue。
这里涉及到队列优先级问题。Handler推送目标Message时,会先通过循环将目标Message的执行时间与MessageQueue里原有Message的执行时间进行一一对比,并按照执行时间先后顺序将目标Message插入MessageQueue。
boolean enqueueMessage(Message msg, long when) {
if (msg.target == null) {
throw new IllegalArgumentException("Message must have a target.");
}
if (msg.isInUse()) {
throw new IllegalStateException(msg + " This message is already in use.");
}
synchronized (this) {
//如果当前消息循环已经结束,直接退出
if (mQuitting) {
IllegalStateException e = new IllegalStateException(
msg.target + " sending message to a Handler on a dead thread");
Log.w(TAG, e.getMessage(), e);
msg.recycle();
return false;
}
msg.markInUse();
msg.when = when;
Message p = mMessages;//头部消息
boolean needWake;
//如果队列中没有消息,或者当前进入的消息比消息队列中的消息等待时间短,那么就放在消息队列的头部
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 {
//判断唤醒条件,当前当前消息队列头部消息是屏障消息,且当前插入的消息为异步消息
//且当前消息队列处于无消息可处理的状态
needWake = mBlocked && p.target == null && msg.isAsynchronous();
Message prev;
//循环遍历消息队列,把当前进入的消息放入合适的位置(比较等待时间)
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;
}
//调用nativeWake,以触发nativePollOnce函数结束等待
if (needWake) {
nativeWake(mPtr);
}
}
return true;
}
2.Looper通过loop()方法获取MessageQueue里的Message。
loop()方法会通过死循环不断调用MessageQueue的next方法来获取Message,并判断等待时间,如果还需要等待则等到相应时间后提取Message。
Message next() {
//如果退出消息消息循环,那么就直接退出
final long ptr = mPtr;
if (ptr == 0) {
return null;
}
int pendingIdleHandlerCount = -1; // -1 only during first iteration
int nextPollTimeoutMillis = 0;
for (;;) {
if (nextPollTimeoutMillis != 0) {
Binder.flushPendingCommands();
}
//执行native层消息机制层,
//timeOutMillis参数为超时等待时间。如果为-1,则表示无限等待,直到有事件发生为止。
//如果值为0,则无需等待立即返回。该方法可能会阻塞
nativePollOnce(ptr, nextPollTimeoutMillis);
synchronized (this) {
//获取系统开机到现在的时间,如果使用System.currentMillis()会有误差,
final long now = SystemClock.uptimeMillis();
Message prevMsg = null;
Message msg = mMessages;//头部消息
//判断是否是栅栏,同时获取消息队列最近的异步消息
if (msg != null && msg.target == null) {
do {
prevMsg = msg;
msg = msg.next;
} while (msg != null && !msg.isAsynchronous());
}
//获取消息,判断等待时间,如果还需要等待则等待相应时间后唤醒
if (msg != null) {
if (now < msg.when) {//判断当前消息时间,是不是比当前时间大,计算时间差
// Next message is not ready. Set a timeout to wake up when it is ready.
nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);
} else {
// 不需要等待时间或者等待时间已经到了,那么直接返回该消息
mBlocked = false;
if (prevMsg != null) {
prevMsg.next = msg.next;
} else {
mMessages = msg.next;
}
msg.next = null;
if (DEBUG) Log.v(TAG, "Returning message: " + msg);
msg.markInUse();
return msg;
}
} else {
//没有更多的消息了
nextPollTimeoutMillis = -1;
}
// Process the quit message now that all pending messages have been handled.
//判断是否已经退出了
if (mQuitting) {
dispose();
return null;
}
// If first time idle, then get the number of idlers to run.
// Idle handles only run if the queue is empty or if the first message
// in the queue (possibly a barrier) is due to be handled in the future.
//获取空闲时处理任务的handler 用于发现线程何时阻塞等待更多消息的回调接口。
if (pendingIdleHandlerCount < 0
&& (mMessages == null || now < mMessages.when)) {
pendingIdleHandlerCount = mIdleHandlers.size();
}
//如果空闲时处理任务的handler个数为0,继续让线程阻塞
if (pendingIdleHandlerCount <= 0) {
// No idle handlers to run. Loop and wait some more.
mBlocked = true;
continue;
}
//判断当前空闲时处理任务的handler是否是为空
if (mPendingIdleHandlers == null) {
mPendingIdleHandlers = new IdleHandler[Math.max(pendingIdleHandlerCount, 4)];
}
mPendingIdleHandlers = mIdleHandlers.toArray(mPendingIdleHandlers);
}
//只有第一次迭代的时候,才会执行下面代码
for (int i = 0; i < pendingIdleHandlerCount; i++) {
final IdleHandler idler = mPendingIdleHandlers[i];
mPendingIdleHandlers[i] = null; // release the reference to the handler
boolean keep = false;
try {
keep = idler.queueIdle();
} catch (Throwable t) {
Log.wtf(TAG, "IdleHandler threw exception", t);
}
//如果不保存空闲任务,执行完成后直接删除
if (!keep) {
synchronized (this) {
mIdleHandlers.remove(idler);
}
}
}
// 重置空闲的handler个数,因为不需要重复执行
pendingIdleHandlerCount = 0;
//当执行完空闲的handler的时候,新的native消息可能会进入,所以唤醒Native消息机制层
nextPollTimeoutMillis = 0;
}
}
Looper取出Message后会执行message.target.dispatchMessage()方法,即handler的dispatchMessage()方法,并在该方法里执行handleMessage。至此,Handler的一个消息循环结束。
参考文档:
https://www.jianshu.com/p/219701879fe4
https://www.jianshu.com/p/3d8f7ec1017a
网友评论