Android中Looper的quit方法和quitSafely方法

孫群發表於2015-08-13

Looper是通過呼叫loop方法驅動著訊息迴圈的進行: 從MessageQueue中阻塞式地取出一個訊息,然後讓Handler處理該訊息,周而復始,loop方法是個死迴圈方法。

那如何終止訊息迴圈呢?我們可以呼叫Looper的quit方法或quitSafely方法,二者稍有不同。
Looper的quit方法原始碼如下:

public void quit() {
    mQueue.quit(false);
}

Looper的quitSafely方法原始碼如下:

public void quitSafely() {
    mQueue.quit(true);
}

以上兩個方法中mQueue是MessageQueue型別的物件,二者都呼叫了MessageQueue中的quit方法,MessageQueue的quit方法原始碼如下:

void quit(boolean safe) {
        if (!mQuitAllowed) {
            throw new IllegalStateException("Main thread not allowed to quit.");
        }

        synchronized (this) {
            if (mQuitting) {
                return;
            }
            mQuitting = true;

            if (safe) {
                removeAllFutureMessagesLocked();
            } else {
                removeAllMessagesLocked();
            }

            // We can assume mPtr != 0 because mQuitting was previously false.
            nativeWake(mPtr);
        }
}

通過觀察以上原始碼我們可以發現:

當我們呼叫Looper的quit方法時,實際上執行了MessageQueue中的removeAllMessagesLocked方法,該方法的作用是把MessageQueue訊息池中所有的訊息全部清空,無論是延遲訊息(延遲訊息是指通過sendMessageDelayed或通過postDelayed等方法傳送的需要延遲執行的訊息)還是非延遲訊息。

當我們呼叫Looper的quitSafely方法時,實際上執行了MessageQueue中的removeAllFutureMessagesLocked方法,通過名字就可以看出,該方法只會清空MessageQueue訊息池中所有的延遲訊息,並將訊息池中所有的非延遲訊息派發出去讓Handler去處理,quitSafely相比於quit方法安全之處在於清空訊息之前會派發所有的非延遲訊息。

無論是呼叫了quit方法還是quitSafely方法只會,Looper就不再接收新的訊息。即在呼叫了Looper的quit或quitSafely方法之後,訊息迴圈就終結了,這時候再通過Handler呼叫sendMessage或post等方法傳送訊息時均返回false,表示訊息沒有成功放入訊息佇列MessageQueue中,因為訊息佇列已經退出了。

需要注意的是Looper的quit方法從API Level 1就存在了,但是Looper的quitSafely方法從API Level 18才新增進來。

相關文章