1. 程式人生 > >Android的Handler機制原理

Android的Handler機制原理

這裡寫圖片描述

建立流程:

主執行緒建立一個looper(只能有一個Looper),建立looper的同時,會在looper的內部建立一個訊息佇列(MessageQueue) 建立Handler的時候,我們會取出當前執行緒的Looper,不斷的去輪詢MessageQueue中的Message。

整體流程:

Handler在子執行緒中傳送的訊息,實際上就是在MessageQueue中新增一條Message,通過Looper中的訊息迴圈取得Message交給Handler處理。

原始碼分析:

ThreadLocal概念:執行緒區域性變數,是一種多執行緒間併發訪問變數的解決方案。與其synchronized等加鎖的方式不同,ThreadLocal完全不提供鎖,而使用以空間換時間的手段,為每個執行緒提供變數的獨立副本,以保障執行緒安全。 從效能上說,ThreadLocal不具有絕對的優勢,在併發不是很高的時候,加鎖的效能會更好,但作為一套與鎖完全無關的執行緒安全解決方案,在高併發量或者競爭激烈的場景,使用ThreadLocal可以在一定程度上減少鎖競爭。

通過ThreadLocal來建立執行緒的內部變數。只建立一個Looper

 static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();

    public static void prepare() {
        prepare(true);
    }

    private static void prepare(boolean quitAllowed) {
        if (sThreadLocal.get() != null) {
            throw new RuntimeException("Only one Looper may be created per thread");
        }
        sThreadLocal.set(new Looper(quitAllowed));
    }

Looper的構造方法,在建立Looper的時候,MessageQueue物件也被建立好了,這樣就能保證Looper中持有一個MessageQueue

    private Looper(boolean quitAllowed) {
        mQueue = new MessageQueue(quitAllowed);
        mThread = Thread.currentThread();
    }

MessageQueue的資料結構其實並不是佇列,這裡採用了單鏈表的形式,因為單鏈表在插入和刪除時,比佇列有優勢。

Handler建立的時候,會呼叫Looper.myLooper這個方法來得到Looper

  mLooper = Looper.myLooper();

Looper.myLooper這個方法其實就是從ThreadLocal中得到Looper

    public static @Nullable Looper myLooper() {
        return sThreadLocal.get();
    }

Handler處理訊息

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

預設情況下,Android中新開啟的執行緒,是沒有開啟訊息迴圈的,如果要線上程中使用Handler,那麼就要先呼叫Looper.prepare,主執行緒中,自動建立了Looper物件

Handler是Looper的一個介面,用來想Looper的MessageQueue中傳送Message

在非UI執行緒中,直接new Handler()是不可以的,因為Handler需要傳送訊息到MessageQueue,而你所在的執行緒中沒有MessageQueue,所以必須要先建立Looper物件。

Android中為什麼主執行緒不會因為Looper.loop()裡的死迴圈卡死?