一 、HandlerThread簡介
從字面意思上看,它既與Handler有關係又與Thread有聯繫。確實如此,它繼承自Thread,是一個線程類,同時又內嵌Looper對象。因此,用它開啓的線程的內部可以直接創建一個Handler,並可以與主線程交互。
關於Looper和Handler的協作請參考安卓學習筆記之android消息機制
二、源碼分析
1、構造方法,用於設置線程名和初始化線程優先級。務必要通過start方法來開啓線程
public HandlerThread(String name) {
super(name);
mPriority = Process.THREAD_PRIORITY_DEFAULT;
}
/**
* Constructs a HandlerThread.
* @param name
* @param priority The priority to run the thread at. The value supplied must be from
*/
public HandlerThread(String name, int priority) {
super(name);
mPriority = priority;
}
2、run方法,初始化Looper對象
可以看到HandlerThread內置了Looper消息循環。onLooperPrepared方法在Looper開始loop之前,做一些初始化或設置。普通Thread的run方法一般都做一些耗時操作,但在此run方法做的是創建Lopper並開啓消息輪循,我們可以在線程的外部通過handler發消息讓它做一些事情。注意,不要試圖重寫其run方法並做耗時操作!
@Override
public void run() {
mTid = Process.myTid();
Looper.prepare();
synchronized (this) {
mLooper = Looper.myLooper();
notifyAll();
}
Process.setThreadPriority(mPriority);
onLooperPrepared();
Looper.loop();
mTid = -1;
}
/**
* Call back method that can be explicitly overridden if needed to execute some
* setup before Looper loops.
*/
protected void onLooperPrepared() {
}
3、獲取Looper對象,用於關聯一個Handler。當線程啓動但Looper沒有創建完成時需等待。
/**
* This method returns the Looper associated with this thread. If this thread not been started
* or for any reason is isAlive() returns false, this method will return null. If this thread
* has been started, this method will block until the looper has been initialized.
* @return The looper.
*/
public Looper getLooper() {
if (!isAlive()) {
return null;
}
// If the thread has been started, wait until the looper has been created.
synchronized (this) {
while (isAlive() && mLooper == null) {
try {
wait();
} catch (InterruptedException e) {
}
}
}
return mLooper;
}
4、 資源回收
由於run方法不會自動停止(Looper.loop()的原因),所以當我們不使用HandlerThread時,可以調用它的quit或quitSafely方法退出線程,否則線程資源得不到回收。
// 直接退出,不處理餘留消息
/**
* Quits the handler thread's looper.
* <p>
* Causes the handler thread's looper to terminate without processing any
* more messages in the message queue.
*/
public boolean quit() {
Looper looper = getLooper();
if (looper != null) {
looper.quit();
return true;
}
return false;
}
//安全退出,等到所有在消息隊列的消息被處理完成。
/**
* Quits the handler thread's looper safely.
* <p>
* Causes the handler thread's looper to terminate as soon as all remaining messages
* in the message queue that are already due to be delivered have been handled.
*/
public boolean quitSafely() {
Looper looper = getLooper();
if (looper != null) {
looper.quitSafely();
return true;
}
return false;
}
三、簡單案例
模擬一個下載任務,在HandlerThread線程中執行耗時操作,並向主線程發送消息以更新UI,當任務完成時,主線程會向子線程發送消息以停止子線程的消息輪循。
package com.yu.threadspool;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Message;
import android.os.SystemClock;
import android.util.Log;
import android.widget.TextView;
public class HandlerThreadTest extends Activity {
public static final int MSG_FROM_MAIN = 0;
public static final int MSG_FROM_THREAD = 1;
public static final int MSG_TASK_DONE = 2;
public static final int MSG_QUIT = 3;
HandlerThread handlerThread;
Handler threadHandler; //子線程
int count = 0;
TextView tv; // 顯示進度
Handler mainHanlder = new Handler() { // 主線程handler
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_FROM_THREAD:
tv.setText((String) msg.obj);
break;
case MSG_TASK_DONE:
tv.setText("完成!");
threadHandler.obtainMessage(MSG_QUIT).sendToTarget();
break;
}
};
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.handler_thread);
tv = (TextView) findViewById(R.id.tv_text);
initHandlerThread();
// 做一些事情,在子線程
threadHandler.post(new Runnable() {
public void run() {
Log.e("TAG", "thread:" + Thread.currentThread().getName());
while (count < 100) {
++count;
Log.e("TAG", "count:" + count);
SystemClock.sleep(200); // 模擬耗時
Message msg = mainHanlder.obtainMessage(MSG_FROM_THREAD,
String.valueOf(count));
msg.sendToTarget(); // 向主線程發送消息,更新UI
}
// 發送任務完成消息
mainHanlder.obtainMessage(MSG_TASK_DONE).sendToTarget();
};
});
}
/**
* 初始化HandlerThread
*/
private void initHandlerThread() {
handlerThread = new HandlerThread("HandlerThread#1");
handlerThread.start(); // 務必要調用,且必須在關聯Handler之前
threadHandler = new Handler(handlerThread.getLooper())// 將threadHandler與handlerThread線程關聯
{
@SuppressLint("NewApi") @Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
if (msg.what == MSG_QUIT) {
handlerThread.getLooper().quitSafely(); // 退出消息輪循,釋放資源
Log.e("TAG", Thread.currentThread().getName()+"退出");
}
}
};
}
}
執行結果
09-08 09:49:45.132: E/TAG(2162): thread:HandlerThread#1
09-08 09:49:45.132: E/TAG(2162): count:1
09-08 09:49:45.332: E/TAG(2162): count:2
09-08 09:49:45.532: E/TAG(2162): count:3
09-08 09:49:45.742: E/TAG(2162): count:4
09-08 09:49:45.942: E/TAG(2162): count:5
... ... (省略部分)
09-08 09:50:04.332: E/TAG(2162): count:96
09-08 09:50:04.532: E/TAG(2162): count:97
09-08 09:50:04.742: E/TAG(2162): count:98
09-08 09:50:04.942: E/TAG(2162): count:99
09-08 09:50:05.142: E/TAG(2162): count:100
09-08 09:50:05.342: E/TAG(2162): HandlerThread#1退出