MessageQueue源碼學習

官方注釋:
MessageQueue是保存消息列表的低級別類,消息由Looper對象派發(fā)。消息并不是直接添加到MessageQueue中的,而是通過與Looper對象關聯(lián)的MessageQueue.IdleHandler對象添加。
調用Looper.myQueue方法可以獲取當前線MessageQueue。

參數(shù)解釋:
private int mPtr; // 使用本機code

表示MessageQueue是否允許退出
mQuitAllowed    

存放IdleHandler對象的一個ArrayList
private final ArrayList<IdleHandler> mIdleHandlers = new 

ArrayList<IdleHandler>();

一個IdleHandler數(shù)組
private IdleHandler[] mPendingIdleHandlers;

判斷Thread是否退出
private boolean mQuitting;

是否被阻塞
private boolean mBlocked;

下一個障礙記號???
private int mNextBarrierToken;

jni調底層的c
private native static long nativeInit();
private native static void nativeDestroy(long ptr);
private native static void nativePollOnce(long ptr, int timeoutMillis);
private native static void nativeWake(long ptr);
private native static boolean nativeIsIdling(long ptr);

IdleHandler在Handler空閑時執(zhí)行,好處在于可以不用指定一個將來時間,只要線程空閑了,就可以執(zhí)行它指定的操作。比較適合那種需要在將來執(zhí)行操作,但是又不知道需要指定多少延遲時間的操作
public static interface IdleHandler {
boolean queueIdle();
}

添加和刪除IdleHandler的方法
addIdleHandler(IdleHandler handler)
removeIdleHandler(IdleHandler handler)

創(chuàng)建消息隊列
MessageQueue(boolean quitAllowed) {
mQuitAllowed = quitAllowed;
mPtr = nativeInit();//通過native方法初始化消息隊列
}

對象銷毀時,該方法finalize()被自動調用。主要是通過native方法銷毀前創(chuàng)建的nativeMessageQueue方法
protected void finalize() throws Throwable {
try {
dispose();
} finally {
super.finalize();
}
}

private void dispose() {
    if (mPtr != 0) {
        nativeDestroy(mPtr);
        mPtr = 0;
    }
}

//next方法會取出下一個Message(從頭部?。?,如果沒有Message可以處理,就可以處理下IdleHandler

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.
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層進行消息標示 0立即返回 -1 等待
//一:是當消息隊列中沒有消息時線程進入等待,二:消息指定了時間,而現(xiàn)在還沒有到這個時間
nativePollOnce(ptr, nextPollTimeoutMillis);

        synchronized (this) {
            // 試圖獲取下一條消息。如果發(fā)現(xiàn)返回。
            final long now = SystemClock.uptimeMillis();
            Message prevMsg = null;
            Message msg = mMessages;
            //尋找下一個異步消息隊列中
            if (msg != null && msg.target == null) {
                do {
                    prevMsg = msg;
                    msg = msg.next;

//(flags & FLAG_ASYNCHRONOUS) != 0; //FLAG_ASYNCHRONOUS = 1 << 1;
} while (msg != null && !msg.isAsynchronous());
}
if (msg != null) {
if (now < msg.when) {
// 下一個消息沒有準備好。設置一個超時時間作為下次休眠的依據(jù)
nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);
} else {
// Got a message.
mBlocked = false;
if (prevMsg != null) {
prevMsg.next = msg.next;
} else {
mMessages = msg.next;
}
msg.next = null;
if (false) Log.v("MessageQueue", "Returning message: " + msg);
return msg;
}
} else {
// 沒有更多信息
nextPollTimeoutMillis = -1;
}

            // 如果還有消息沒處理,交給底層處理
            if (mQuitting) {
                dispose();
                return null;
            }

            //?????
            if (pendingIdleHandlerCount < 0
                    && (mMessages == null || now < mMessages.when)) {
                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);
        }

        // 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);
            }

            if (!keep) {
                synchronized (this) {
                    mIdleHandlers.remove(idler);
                }
            }
        }

        // Reset the idle handler count to 0 so we do not run them again.
        pendingIdleHandlerCount = 0;

        // While calling an idle handler, a new message could have been delivered
        // so go back and look again for a pending message without waiting.
        nextPollTimeoutMillis = 0;
    }
}

總結:
每個Message之間是串連在一起的,Message只要知道自己的前面一個Message和后面一個Message就可以了,Message之間的排序通過用時間戳來排序,時間戳小的排在前面。

再配合上handler對于消息的取出,第一個Message的時間到了,就取隊列的第一個Message,取完之后,將第一個Message置空,這樣第二個Message就排在第一個了,依此類推。

遺留問題:
1.pendingIdleHandlerCount < 0 完后為什么還有一個
pendingIdleHandlerCount <= 0 的判斷,為什么這樣寫?
2.if (false) Log.v 這個false的寫法奇怪?
3.為什么一定要用jni來處理?

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容