Handler原理

Handler原理注意是消息處理機(jī)制。

  1. Message:消息的bean類,主要包含what,data, callback等信息;
  2. Handler:消息的搬運工,主要是發(fā)送和處理;
  3. MessageQueue:消息隊列,主要是效果的管理;
  4. Looper:在ThreadLocal里面,用來啟動MessageQueue,會調(diào)用MessageQueue的next方法。主線程默認(rèn)啟動了
 for (;;) {
            Message msg = queue.next(); // might block

消息隊列啟動。

通過Looper.loop()啟動,主線程默認(rèn)啟動了,其他線程需要自己啟動,否則不能進(jìn)行消息處理。
ThreadLocal:構(gòu)造方法是私有,通過獲取當(dāng)前的線程作為變量,保證每個線程的ThreadLocal只會是調(diào)用者的。

消息分發(fā)

如果是post還是postDelay,最終都會調(diào)用到:

public final boolean sendMessageDelayed(@NonNull Message msg, long delayMillis) {
        if (delayMillis < 0) {
            delayMillis = 0;
        }
        return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
    }

這是系統(tǒng)的開機(jī)時間,所以系統(tǒng)休眠了,會到延時處理失敗。
消息隊列排序:在MessageQueue.enqueueMessage插入的時候排序

 if (p == null || when == 0 || when < p.when) {
                // New head, wake up the event queue if blocked.
                msg.next = p;
                mMessages = msg;
                needWake = mBlocked;
            } else {
                // Inserted within the middle of the queue.  Usually we don't have to wake
                // up the event queue unless there is a barrier at the head of the queue
                // and the message is the earliest asynchronous message in the queue.
                needWake = mBlocked && p.target == null && msg.isAsynchronous();
                Message prev;
                for (;;) {
                    prev = p;
                    p = p.next;
                    if (p == null || when < p.when) {
                        break;
                    }
                    if (needWake && p.isAsynchronous()) {
                        needWake = false;
                    }
                }
                msg.next = p; // invariant: p == prev.next
                prev.next = msg;
            }

根據(jù)代碼如果我們要實現(xiàn)一個高優(yōu)先級的消息,只需要把當(dāng)前時間設(shè)置會0,就會插入到堆首,以保證可以快速響應(yīng)。

消息分發(fā)

根據(jù)Looper.loop()方法,會不斷調(diào)用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();
            }

            nativePollOnce(ptr, nextPollTimeoutMillis);

內(nèi)部也是一個死循環(huán),會不斷暫停在nativePollOnce方法中,nextPollTimeoutMillis是暫停時間,其中的是遍歷所有消息隊列得到的值。-1表示永久阻塞,直至有新消息進(jìn)來,喚醒。
next方法會返回下一個需要處理的消息。

if (msg != null) {
                    if (now < msg.when) {
                        // Next message is not ready.  Set a timeout to wake up when it is ready.
                        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 (DEBUG) Log.v(TAG, "Returning message: " + msg);
                        msg.markInUse();
                        return msg;
                    }
                } else {
                    // No more messages.
                    nextPollTimeoutMillis = -1;
                }

獲取到待處理Message,Looper會調(diào)用dispatchMessage方法

  try {
                msg.target.dispatchMessage(msg);
                if (observer != null) {
                    observer.messageDispatched(token, msg);
                }
                dispatchEnd = needEndTime ? SystemClock.uptimeMillis() : 0;
            } 

target:Message的handler,最終調(diào)用:

 /**
     * Handle system messages here.
     */
    public void dispatchMessage(@NonNull Message msg) {
        if (msg.callback != null) {
            handleCallback(msg);
        } else {
            if (mCallback != null) {
                if (mCallback.handleMessage(msg)) {
                    return;
                }
            }
            handleMessage(msg);
        }
    }

最后就會執(zhí)行我們重寫的handleMessage方法。

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

友情鏈接更多精彩內(nèi)容