關于Handler的原理溜族,看了很多博客,個人認為以下三篇文章講的不錯垦沉,第一篇篇幅最短煌抒,雖然沒有源碼講解,但結合流程圖概括的很精煉厕倍;第二篇稍長寡壮,是CSDN博客專家——鴻洋寫的,結合源碼分析讹弯,簡單易懂况既;最后一篇就更詳細但也更冗長了:
Android應用程序消息處理機制
Android 異步消息處理機制 讓你深入理解 Looper、Handler组民、Message三者關系
Android 消息處理機制(Looper坏挠、Handler、MessageQueue,Message)
最后一篇中作者有條結論:
Handler 對象在哪個線程下構建(Handler的構造函數(shù)在哪個線程下調(diào)用)邪乍,那么Handler 就會持有這個線程的Looper引用和這個線程的消息隊列的引用。因為持有這個線程的消息隊列的引用对竣,意味著這個Handler對象可以在任意其他線程給該線程的消息隊列添加消息庇楞,也意味著Handler的handleMessage 肯定也是在該線程執(zhí)行的。
以上結論其實只概括了一部分否纬,因為Handler的構造方法有很多種吕晌,以上結論只適用于不傳Looper的構造方法,諸如:
public Handler()
public Handler(Callback callback)
這些構造方法默認與當前線程的Looper綁定【通過mLooper = Looper.myLooper();】临燃,所以說哪個線程創(chuàng)建了Handler對象睛驳,handleMessage就在哪個線程執(zhí)行烙心。
但是當使用參數(shù)中含有Looper的構造方法時,諸如:
public Handler(Looper looper)
public Handler(Looper looper, Callback callback)
那么此時無論Handler對象是在哪個線程構建的乏沸,該Handler對象所持有的Looper和MessageQueue都是構造方法中傳入的那個Looper淫茵,而這個Looper一般都是與其他線程綁定的(否則就沒必要使用這個構造函數(shù)了),此時相當于在當前線程下構造了一個與指定線程綁定的Handler對象蹬跃,可以通過該Handler對象向指定線程發(fā)送消息匙瘪,當然該Handler對象的handlerMessage也是運行在指定線程上的。
所以蝶缀,可以得出結論丹喻,handler對象所綁定的線程其實并不取決于該handler對象由哪個線程構建,而是取決于該handler對象所綁定的Looper屬于哪個線程翁都。
以下的demo可以驗證結論:
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());
}
// 對外提供一個方法碍论,用于發(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運行后柄慰,最終輸出為:
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的一個成員變量鳍悠,而MyHandlerThread是在線程1673構建的,所以這個handler對象也是在1673構建的先煎,然而最終handleMessage是在線程1674上執(zhí)行的贼涩,也就是構建handler對象時傳入的t2.getLooper()所對應的線程t2。