關(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。