return;
}
···
msg.recycleUnchecked();
}
}
可以看到,loop 方法中存在一个for(;;)
死循环,如果该方法中 queue.next()
方法返回 null ,那么直接 return 退出整个死循环,整个ActivityThread.main()
方法也就结束了,整个程序也就退出了。但是我们的程序肯定是一直在运行的,也就是说 queue.next()
方法中一直有消息,但是如果一段时间没有操作了,整个程序也就没有执行的消息了,那为什么程序还能一直运行呢,所以问题肯定就在 queue.next()
这个方法中。
该方法中也有一个 for(;;)
死循环,里面有一个关键方法 nativePollOnce
@UnsupportedAppUsage
Message next() {
// Return here if the message loop has already quit and been disposed.
// This can happen if the application tries to restart a looper after quit
// which is not supported.
···
int nextPollTimeoutMillis = 0;
for (;😉 {
if (nextPollTimeoutMillis != 0) {
Binder.flushPendingCommands();
}
···
nativePollOnce(ptr, nextPollTimeoutMillis); //没有消息,阻塞等待
···
}
}
该方法在 nextPollTimeoutMillis = -1
的时候就阻塞等待,直到下一条消息可用为止。否则就继续向下执行。那我们再看看是在哪里唤醒的呢?是在消息入队最终执行的方法 enqueueMessage 中:
boolean enqueueMessage(Message msg, long when) {
···
// We can assume mPtr != 0 because mQuitting is false.
if (needWake) {
nativeWake(mPtr);
}
}
return true;
}
在 nativeWake 方法中进行唤醒,就是唤醒上面的那个地方,没有消息的时候,这里就处于阻塞状态。
这样我们把消息处理机制的整个逻辑大概梳理了一下,为什么需要理清呢,因为 IdleHandler 是在消息队列没有消息或者是在有暂时不需要处理的消息(延迟消息),就是说这个时候是空闲的,进行 IdleHandler 进行处理的。所以我们可以猜测 IdleHandler 应该也在 next 方法中进行触发它的方法。事实也确实如此:
Message next() {
…
for (;😉 {
…
synchronized (this) {
// 此处为正常消息队列的处理
…
if (mQuitt