Android Handler機(jī)制 - handleMessage究竟在哪個(gè)線程執(zhí)行

關(guān)于Handler的原理,看了很多博客,個(gè)人認(rèn)為以下三篇文章講的不錯(cuò),第一篇篇幅最短,雖然沒有源碼講解,但結(jié)合流程圖概括的很精煉;第二篇稍長,是CSDN博客專家——鴻洋寫的,結(jié)合源碼分析,簡單易懂;最后一篇就更詳細(xì)但也更冗長了:

Android應(yīng)用程序消息處理機(jī)制
Android 異步消息處理機(jī)制 讓你深入理解 Looper、Handler、Message三者關(guān)系
Android 消息處理機(jī)制(Looper、Handler、MessageQueue,Message)

最后一篇中作者有條結(jié)論:

Handler 對象在哪個(gè)線程下構(gòu)建(Handler的構(gòu)造函數(shù)在哪個(gè)線程下調(diào)用),那么Handler 就會持有這個(gè)線程的Looper引用和這個(gè)線程的消息隊(duì)列的引用。因?yàn)槌钟羞@個(gè)線程的消息隊(duì)列的引用,意味著這個(gè)Handler對象可以在任意其他線程給該線程的消息隊(duì)列添加消息,也意味著Handler的handleMessage 肯定也是在該線程執(zhí)行的。

以上結(jié)論其實(shí)只概括了一部分,因?yàn)镠andler的構(gòu)造方法有很多種,以上結(jié)論只適用于不傳Looper的構(gòu)造方法,諸如:

public Handler()
public Handler(Callback callback)

這些構(gòu)造方法默認(rèn)與當(dāng)前線程的Looper綁定【通過mLooper = Looper.myLooper();】,所以說哪個(gè)線程創(chuàng)建了Handler對象,handleMessage就在哪個(gè)線程執(zhí)行。
但是當(dāng)使用參數(shù)中含有Looper的構(gòu)造方法時(shí),諸如:

public Handler(Looper looper)
public Handler(Looper looper, Callback callback)

那么此時(shí)無論Handler對象是在哪個(gè)線程構(gòu)建的,該Handler對象所持有的Looper和MessageQueue都是構(gòu)造方法中傳入的那個(gè)Looper,而這個(gè)Looper一般都是與其他線程綁定的(否則就沒必要使用這個(gè)構(gòu)造函數(shù)了),此時(shí)相當(dāng)于在當(dāng)前線程下構(gòu)造了一個(gè)與指定線程綁定的Handler對象,可以通過該Handler對象向指定線程發(fā)送消息,當(dāng)然該Handler對象的handlerMessage也是運(yùn)行在指定線程上的。
所以,可以得出結(jié)論,handler對象所綁定的線程其實(shí)并不取決于該handler對象由哪個(gè)線程構(gòu)建,而是取決于該handler對象所綁定的Looper屬于哪個(gè)線程。
以下的demo可以驗(yàn)證結(jié)論:
MyHandlerThread.java:

package com.example.weishj.mytester.handler;

import android.os.Handler;
import android.os.Message;
import android.util.Log;

/**
 * Created by weishj on 2017/6/21.
 */

public abstract class MyHandlerThread implements Handler.Callback {
    protected final Handler handler;

    public MyHandlerThread() {
        Log.e("MyHandlerThread", "Create MyHandlerThread. tid=" + Thread.currentThread().getId());
        android.os.HandlerThread t2 = new android.os.HandlerThread("MyHandlerThread");
        t2.start();
        Log.e("MyHandlerThread", "start t2. t2.tid=" + t2.getId());
        this.handler = new Handler(t2.getLooper(), this); // handler持有的是t2的Looper和MessageQueue
    }

    public final boolean handleMessage(Message msg) {
        // 處理this.handler發(fā)過來的消息
        switch(msg.what) {
            case 1:
                Log.e("MyHandlerThread", "handled message. tid=" + Thread.currentThread().getId());
                break;
            default:
                break;
        }
        return false;
    }
}

Sub.java:


package com.example.weishj.mytester.handler;

import android.os.Message;
import android.util.Log;

/**
 * Created by weishj on 2017/6/21.
 */

public class Sub extends MyHandlerThread {
    public Sub() {
        Log.e("Sub", "Create Sub. tid=" + Thread.currentThread().getId());
    }
    // 對外提供一個(gè)方法,用于發(fā)送消息
    public void sendMessage() {
        Message msg = new Message();
        msg.what = 1;
        msg.obj = "test data";
        super.handler.sendMessage(msg);
    }
}

MainActivity.java:

package com.example.weishj.mytester;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;

import com.example.weishj.mytester.handler.Sub;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Log.e("MainActivity", "MainActivity onCreate. tid=" + Thread.currentThread().getId());
        // 我在程序的某處, 如此調(diào)用
        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                Sub sub = new Sub();
                sub.sendMessage();
            }
        });
        t1.start();
        Log.e("MainActivity", "Start t1. t1.tid=" + t1.getId());
    }
}

demo運(yùn)行后,最終輸出為:
06-22 10:36:44.607 2305-2305/com.example.weishj.mytester E/MainActivity: MainActivity onCreate. tid=1
06-22 10:36:44.608 2305-2305/com.example.weishj.mytester E/MainActivity: Start t1. t1.tid=1673
06-22 10:36:44.609 2305-2381/com.example.weishj.mytester E/MyHandlerThread: Create MyHandlerThread. tid=1673
06-22 10:36:44.610 2305-2381/com.example.weishj.mytester E/MyHandlerThread: start t2. t2.tid=1674
06-22 10:36:44.610 2305-2381/com.example.weishj.mytester E/Sub: Create Sub. tid=1673
06-22 10:36:44.613 2305-2382/com.example.weishj.mytester E/MyHandlerThread: handled message. tid=1674
handler對象是MyHandlerThread的一個(gè)成員變量,而MyHandlerThread是在線程1673構(gòu)建的,所以這個(gè)handler對象也是在1673構(gòu)建的,然而最終handleMessage是在線程1674上執(zhí)行的,也就是構(gòu)建handler對象時(shí)傳入的t2.getLooper()所對應(yīng)的線程t2。

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

相關(guān)閱讀更多精彩內(nèi)容

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