Android應(yīng)用程序消息處理機(jī)制(Looper、Handler)分析(7)
如果消息隊(duì)列中有消息,并且當(dāng)前時(shí)候大于等于消息中的執(zhí)行時(shí)間,那么就直接返回這個(gè)消息給Looper.loop消息處理,否則的話就要等待到消息的執(zhí)行時(shí)間:
[java] view plaincopynextPollTimeoutMillis = (int) Math.min(when - now, Integer.MAX_VALUE);
如果消息隊(duì)列中沒有消息,那就要進(jìn)入無窮等待狀態(tài)直到有新消息了:
[java] view plaincopynextPollTimeoutMillis = -1;
-1表示下次調(diào)用nativePollOnce時(shí),如果消息中沒有消息,就進(jìn)入無限等待狀態(tài)中去。
當(dāng)前nativePollOnce返回后,就去看看消息隊(duì)列中有沒有消息:
- [java] view plaincopyfinal Message msg = mMessages;
- if (msg != null) {
- final long when = msg.when;
- if (now >= when) {
- mBlocked = false;
- mMessages = msg.next;
- msg.next = null;
- if (Config.LOGV) Log.v("MessageQueue", "Returning message: " + msg);
- return msg;
- } else {
- nextPollTimeoutMillis = (int) Math.min(when - now, Integer.MAX_VALUE);
- }
- } else {
- nextPollTimeoutMillis = -1;
- }
這里計(jì)算出來的等待時(shí)間都是在下次調(diào)用nativePollOnce時(shí)使用的。
這里說的等待,是空閑等待,而不是忙等待,因此,在進(jìn)入空閑等待狀態(tài)前,如果應(yīng)用程序注冊了IdleHandler接口來處理一些事情,那么就會(huì)先執(zhí) 行這里IdleHandler,然后再進(jìn)入等待狀態(tài)。IdlerHandler是定義在MessageQueue的一個(gè)內(nèi)部類:
- [java] view plaincopypublic class MessageQueue {
- ......
- /**
- * Callback interface for discovering when a thread is going to block
- * waiting for more messages.
- */
- public static interface IdleHandler {
- /**
- * Called when the message queue has run out of messages and will now
- * wait for more. Return true to keep your idle handler active, false
- * to have it removed. This may be called if there are still messages
- * pending in the queue, but they are all scheduled to be dispatched
- * after the current time.
- */
- boolean queueIdle();
- }
- ......
- }
它只有一個(gè)成員函數(shù)queueIdle,執(zhí)行這個(gè)函數(shù)時(shí),如果返回值為false,那么就會(huì)從應(yīng)用程序中移除這個(gè)IdleHandler,否則的話就會(huì)在 應(yīng)用程序中繼續(xù)維護(hù)著這個(gè)IdleHandler,下次空閑時(shí)仍會(huì)再執(zhí)會(huì)這個(gè)IdleHandler。MessageQueue提供了 addIdleHandler和removeIdleHandler兩注冊和刪除IdleHandler。
回到MessageQueue函數(shù)中,它接下來就是在進(jìn)入等待狀態(tài)前,看看有沒有IdleHandler是需要執(zhí)行的:
- [java] view plaincopy// If first time, then get the number of idlers to
- run.
- if (pendingIdleHandlerCount < 0) {
- pendingIdleHandlerCount = mIdleHandlers.size();
- }
- if (pendingIdleHandlerCount == 0) {
- // No idle handlers to run. Loop and wait some more.
- mBlocked = true;
- continue;
- }
- if (mPendingIdleHandlers == null) {
- mPendingIdleHandlers = new IdleHandler[Math.max(pendingIdleHandlerCount,
- 4)];
- }
- mPendingIdleHandlers = mIdleHandlers.toArray(mPendingIdleHandlers);
如果沒有,即pendingIdleHandlerCount等于0,那下面的邏輯就不執(zhí)行了,通過continue語句直接進(jìn)入下一次循環(huán),否則就要把 注冊在mIdleHandlers中的IdleHandler取出來,放在mPendingIdleHandlers數(shù)組中去。
接下來就是執(zhí)行這些注冊了的IdleHanlder了:
- [java] view plaincopy// Run the idle handlers.
- // We only ever reach this code block during the first iteration.
- 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("MessageQueue", "IdleHandler threw exception", t);