Android原始碼解析之(四)-->HandlerThread
上一篇文章中我們講解了AsyncTast的基本使用以及實現原理,我們知道AsyncTask內部是通過執行緒池和Handler實現的,通過對執行緒池和handler的封裝實現了對非同步任務操作。更多關於AsyncTask相關的內容,可參考我的android原始碼解析之(三)–>非同步任務AsyncTask
本文我們將講解HandlerThread相關的概念。HandlerThread是什麼東西呢?瞭解一個類最好的方法就是檢視類的定義,所以我們就看一下HandlerThread是如何定義的吧。檢視類的定義時有這樣一段話:
Handy class for starting a new thread that has a looper.
The looper can then be used to create handler classes.
Note that start() must still be called.
意思就是說:這個類的作用是建立一個包含looper的執行緒。
那麼我們在什麼時候需要用到它呢?加入在應用程式當中為了實現同時完成多個任務,所以我們會在應用程式當中建立多個執行緒。為了讓多個執行緒之間能夠方便的通訊,我們會使用Handler實現執行緒間的通訊。這個時候我們手動實現的多執行緒+Handler的簡化版就是我們HandlerThrea所要做的事了。
下面我們首先看一下HandlerThread的基本用法:
/**
* 測試HandlerThread的基本使用
*/
HandlerThread mHandlerThread = new HandlerThread("myHandlerThreand");
mHandlerThread.start();
// 建立的Handler將會在mHandlerThread執行緒中執行
final Handler mHandler = new Handler(mHandlerThread.getLooper()) {
@Override
public void handleMessage(Message msg) {
Log.i("tag", "接收到訊息:" + msg.obj.toString());
}
};
title = (TextView) findViewById(R.id.title);
title.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Message msg = new Message();
msg.obj = "11111";
mHandler.sendMessage(msg);
msg = new Message();
msg.obj = "2222";
mHandler.sendMessage(msg);
}
});
我們首先定義了一個HandlerThread物件,是直接通過new的方式產生的,檢視其構造方法:
public HandlerThread(String name) {
super(name);
mPriority = Process.THREAD_PRIORITY_DEFAULT;
}
可以知道HandlerThread繼承於Thread,所以說HandlerThread本質上是一個執行緒,其構造方法主要是做一些初始化的操作。
然後我們呼叫了mHandlerThread.start()方法,由上我們知道了HandlerThread類其實就是一個Thread,一個執行緒,所以其start方法內部呼叫的肯定是Thread的run方法,我們檢視一下其run方法的具體實現:
@Override
public void run() {
mTid = Process.myTid();
Looper.prepare();
synchronized (this) {
mLooper = Looper.myLooper();
notifyAll();
}
Process.setThreadPriority(mPriority);
onLooperPrepared();
Looper.loop();
mTid = -1;
}
我們發現其內部呼叫了Looper.prepate()方法和Loop.loop()方法,熟悉android非同步訊息機制的童鞋應當知道,在android體系中一個執行緒其實是對應著一個Looper物件、一個MessageQueue物件,以及N個Handler物件,具體可參考:android原始碼解析之(二)–>非同步訊息機制
所以通過run方法,我們可以知道在我們建立的HandlerThread執行緒中我們建立了該執行緒的Looper與MessageQueue;
這裡需要注意的是其在呼叫Looper.loop()方法之前呼叫了一個空的實現方法:onLooperPrepared(),我們可以實現自己的onLooperPrepared()方法,做一些Looper的初始化操作;
run方法裡面當mLooper建立完成後有個notifyAll(),getLooper()中有個wait(),這是為什麼呢?因為的mLooper在一個執行緒中執行,而我們的handler是在UI執行緒初始化的,也就是說,我們必須等到mLooper建立完成,才能正確的返回getLooper();wait(),notify()就是為了解決這兩個執行緒的同步問題
然後我們呼叫了:
// 建立的Handler將會在mHandlerThread執行緒中執行
final Handler mHandler = new Handler(mHandlerThread.getLooper()) {
@Override
public void handleMessage(Message msg) {
Log.i("tag", "接收到訊息:" + msg.obj.toString());
}
};
該Handler的構造方法中傳入了HandlerThread的Looper物件,所以Handler物件就相當於含有了HandlerThread執行緒中Looper物件的引用。
然後我們呼叫handler的sendMessage方法傳送訊息,在Handler的handleMessge方法中就可以接收到訊息了。
最後需要注意的是在我們不需要這個looper執行緒的時候需要手動停止掉;
protected void onDestroy() {
super.onDestroy();
mHandlerThread.quit();
}
好了,以上就是HandlerThread相關的知識了,相對來說HandlerThread還是比較簡單的,其本質上就是一個Thread執行緒,只不過裡面包含了Looper和MessageQueue,最後我們在這裡總結一下。
總結:
HandlerThread本質上是一個Thread物件,只不過其內部幫我們建立了該執行緒的Looper和MessageQueue;
通過HandlerThread我們不但可以實現UI執行緒與子執行緒的通訊同樣也可以實現子執行緒與子執行緒之間的通訊;
HandlerThread在不需要使用的時候需要手動的回收掉;