Handler、Looper、Message隨筆

一個暱稱而已T發表於2017-09-13

在子執行緒中實現Handler的大致操作:

    mThread = new Thread() {
            @Override
            public void run() {
                Looper.prepare();//Looper.prepare()是在後臺輪詢執行緒中呼叫的
                // Looper用於封裝了android執行緒中的訊息迴圈,預設情況下一個執行緒是不存在訊息迴圈(message loop)的,
                // 需要呼叫Looper.prepare()來給執行緒建立一個訊息迴圈,呼叫Looper.loop()來使訊息迴圈起作用,
                // 從訊息佇列裡取訊息,處理訊息。

                // 定義Handler的邏輯,Handler在哪個執行緒初始化就屬於哪個執行緒
                mThreadHandler = new Handler() {
                    @Override
                    public void handleMessage(Message msg) {
                        //TODO
                    }
                };
                ...
                Looper.loop();
            }
        };

        mThread.start();

等到mThreadHandler 初始化之後,就可以在其他地方使用mThreadHandler 傳送Message了。

具體的使用可以參考:Android-仿微信圖片選擇器中ImageLoader類的實現


Android 非同步訊息處理機制 讓你深入理解 Looper、Handler、Message三者關係

摘錄:

Looper主要作用:
1、  與當前執行緒繫結,保證一個執行緒只會有一個Looper例項,同時一個Looper例項也只有一個MessageQueue。
2loop()方法,不斷從MessageQueue中去取訊息,交給訊息的target屬性的dispatchMessage去處理。

Handler部分原始碼

public Handler() {  
        this(null, false);  
}  
public Handler(Callback callback, boolean async) {  
        if (FIND_POTENTIAL_LEAKS) {  
            final Class<? extends Handler> klass = getClass();  
            if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&  
                    (klass.getModifiers() & Modifier.STATIC) == 0) {  
                Log.w(TAG, "The following Handler class should be static or leaks might occur: " +  
                    klass.getCanonicalName());  
            }  
        }  

        mLooper = Looper.myLooper();  
        if (mLooper == null) {  
            throw new RuntimeException(  
                "Can't create handler inside thread that has not called Looper.prepare()");  
        }  
        mQueue = mLooper.mQueue;  
        mCallback = callback;  
        mAsynchronous = async;  
    } 

Handler如何與如何與MessageQueue聯絡上的:
14行:通過Looper.myLooper()獲取了當前執行緒儲存的Looper例項,然後在19行又獲取了這個Looper例項中儲存的MessageQueue(訊息佇列),這樣就保證了handler的例項與我們Looper例項中MessageQueue關聯上了。
總結:
1、首先Looper.prepare()在本執行緒中儲存一個Looper例項,然後該例項中儲存一個MessageQueue物件;因為Looper.prepare()在一個執行緒中只能呼叫一次,所以MessageQueue在一個執行緒中只會存在一個。
2、Looper.loop()會讓當前執行緒進入一個無限迴圈,不斷從MessageQueue的例項中讀取訊息(通過queue.next()),然後回撥msg.target.dispatchMessage(msg)方法。
3、Handler的構造方法,會首先得到當前執行緒中儲存的Looper例項,進而與Looper例項中的MessageQueue相關聯。
4、Handler的sendMessage方法,會給msg的target賦值為handler自身,然後加入MessageQueue中。
5、在構造Handler例項時,我們會重寫handleMessage方法,也就是msg.target.dispatchMessage(msg)最終呼叫的方法。

圖解
這裡寫圖片描述


Android 進階14:原始碼解讀 Android 訊息機制( Message MessageQueue Handler Looper)
相比於鴻揚的部落格,講得比較詳細


Android 中Message,MessageQueue,Looper,Handler詳解+例項
有結合例項在子執行緒中建立Handler

相關文章