1. 程式人生 > >android Looper Handler機制

android Looper Handler機制

在具體看原始碼之前,我已經知道了MyMessage中有一個成員變數Handler target來儲存handle,於是我寫一個簡易模擬程式。
考慮因素如下:
1、應用程式無論是哪個MyHandler sendMessage過來的,都可以用一個looper進行處理。
2、MyLooper要有不斷提取訊息和處理訊息的能力,那麼要繼承Thread。使用一個List list來儲存訊息,run方法不斷取和獲取MyMessage中的target,呼叫handlerMessage方法即可。
類圖大概是這樣的:
這裡寫圖片描述

當你想強行加一些prepare、loop等函式的時候,你會覺得很雞肋。
而且考慮到多執行緒雖然用同一個MyLooper可行,但是每個執行緒的生命週期和處理的時間不一,不應該採用一個MyLooper物件。帶著一些疑問我們看看原始碼是怎麼寫的。
1、Handler如何獲取Looper中的訊息佇列


預設建構函式呼叫this(null, false);

Handler.java
public Handler(Callback callback, boolean async) {
        ...
        mLooper = Looper.myLooper();
        mQueue = mLooper.mQueue;
}

Looper.myLooper();是獲取當前執行緒的Looper物件,此物件有成員mQueue。
handle算了與訊息佇列聯絡起來了,方法sendMessage呼叫了enqueueMessage,將訊息放去佇列

Handler.java
 private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
        msg.target = this;
        ...
return queue.enqueueMessage(msg, uptimeMillis); }

2、那Looper是怎麼跟當前執行緒形成一對一關係的

Looper.java
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)); }

可見prepare就是為了建立Looper,然後與當前執行緒繫結。
Looper類中成員變數static final ThreadLocal sThreadLocal = new ThreadLocal(); 儲存著執行緒和對應looper物件。
之前handle建構函式的Looper.myLooper();語句,其實是

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

sThreadLocal.get(); 返回當前執行緒looper物件。
3、所以Looper中loop方法先要獲取當前執行緒looper物件,然後得其訊息佇列。

 public static void loop() {
        final Looper me = myLooper();
        ...
        for (;;) {
            Message msg = queue.next(); // might block
            ...
            msg.target.dispatchMessage(msg);
            ...
            msg.recycle();
        }
    }

4、Handle訊息處理順序

public void dispatchMessage(Message msg) {
        if (msg.callback != null) {
            handleCallback(msg);
        } else {
            if (mCallback != null) {
                if (mCallback.handleMessage(msg)) {
                    return;
                }
            }
            handleMessage(msg);
        }
    }

先msg的回撥方法,再就是handle自身回撥方法,最後是handleMessage方法.

自此我們瞭解了Looper Handle機制”是什麼”,但更值得思考的是”為什麼”。
5、一對一的對應關係可以採用組合的方式實現,即執行緒裡面有Looper成員變數,應思考設計中的高內聚低耦合