public static void loop() {
final Looper me = myLooper();
final MessageQueue queue = me.mQueue;
for (;😉 {
Message msg = queue.next(); // might block
try {
msg.target.dispatchMessage(msg);
} // …
}
}
可以发现,loop()
函数其实是一个死循环;在这个循环中,不停地从消息队列中取下一条消息,然后分发给对应的Handler(msg.target
)进行处理。 “Looper”就是循环的意思,这正对应了loop()
方法中的这个死循环。在这个死循环里面,可以无限读取消息队列中的消息。使用quit()
方法可以退出这个循环;如果在主线程的Looper退出,也就意味着程序的结束——将会得到 java.lang.IllegalStateException: Main thread not allowed to quit.
的报错信息。
1.2 消息队列 - MessageQueue
- Message
Message消息是Handler传递信息的基本单位。在Handler中,不管是调用post(Runnable)
还是sendMessage(Message)
还是其他的什么,最终都会构建一个Message对象,并添加到消息队列mQueue
中。Message中保存了消息的类型、参数、对应的Handler等一些少量的数据。
在1.1中说到,Looper.loop()
会发起一个死循环,在消息队列中不停取值。那么,为什么这里不会卡死呢?
Looper#loop()
:
public static void loop() {
final Looper me = myLooper();
final MessageQueue queue = me.mQueue;
for (;😉 {
Message msg = queue.next(); // might block
try {
msg.target.dispatchMessage(msg);
} // …
}
}
跳转到MessageQueue.next()
,看一下消息队列是怎么取下一条消息的。这里删去了大部分代码,只剩下核心的部分,方便梳理流程:
Message next() {
int nextPollTimeoutMillis = 0;
for (;😉 {
nativePollOnce(ptr, nextPollTimeoutMillis); // 会阻塞线程直到下一个消息到来
synchronized (this) {
final long now = SystemClock.uptimeMillis();
Message msg = mMessages;
if (msg != null) {
if (now < msg.when) { // 时候未到
nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);
} else {
mMessages = msg.next;
msg.next = null;
msg.markInUse();
return msg;
}
}
}
}
}
nativePollOnce
是一个本地方法,它会阻塞线程直到下一个有消息来临。这类似于Java中的DelayQueue
,不同点是DelayQueue
是通过优先队列+锁实现的。 在MessageQueue中有一个Message类型的对象mMessage
,它保存着消息队列中最早的一条消息。当阻塞的线程被唤醒时,next()