一 、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退出