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()裏的死循環卡死?

https://www.zhihu.com/question/34652589

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章