HandlerThread,顾名思义,本质上它是一种与Handler共同协作执行任务的Thread。
一、源码分析
HandlerThread的实现过程非常简单,总共也就一百多行代码,整个类的核心过程就是在run方法中通过Looper.prepare()创建消息队列并通过Looper.loop()开启消息循环,这个Looper就是我们连接Handler的媒介。我们首先来看看它的内部实现:
/**
* 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.
*/
public class HandlerThread extends Thread {
int mPriority;
int mTid = -1;
Looper mLooper;
private Handler mHandler;
/**
* 构造函数,设置线程名称,优先级默认
*/
public HandlerThread(String name) {
super(name);
mPriority = Process.THREAD_PRIORITY_DEFAULT;
}
/**
* 构造函数,设置线程名称和优先级
*/
public HandlerThread(String name, int priority) {
super(name);
mPriority = priority;
}
@Override
public void run() {
mTid = Process.myTid();
Looper.prepare(); //创建Looper对象 & 消息队列
synchronized (this) { //通过锁机制获取当前线程的Looper对象
mLooper = Looper.myLooper();
notifyAll(); //通知getLooper方法looper已经创建成功,对应getLooper方法中的wait()
}
Process.setThreadPriority(mPriority); //设置线程优先级
onLooperPrepared(); //重写此方法,作用是在消息循环之前进行一些准备工作
Looper.loop(); //开启消息循环
mTid = -1;
}
/**
* 消息循环前的准备工作,根据需求决定是否重写
*/
protected void onLooperPrepared() {
}
/**
* 使用同步锁机制获取当前线程Looper。这是为了保证只有当线程创建成功并且其
* 对应的Looper对象也创建成功后才能获得Looper的值,然后才能将创建的Handler
* 与工作线程的Looper对象绑定,从而将任务切换到Looper绑定工作线程中执行
*/
public Looper getLooper() {
if (!isAlive()) { //线程还未开启,返回null
return null;
}
// 使用对象锁机制:如果线程已开启, 进入等待状态直到looper成功初始化.
synchronized (this) {
while (isAlive() && mLooper == null) {
try {
wait(); //等待Looper初始化完成,对应run方法中的notifyAll
} catch (InterruptedException e) {
}
}
}
return mLooper;
}
/**
* @return a shared {@link Handler} associated with this thread
* @hide
*/
public Handler getThreadHandler() {
if (mHandler == null) {
mHandler = new Handler(getLooper());
}
return mHandler;
}
/**
* 直接退出线程的消息循环(强行退出循环)
*/
public boolean quit() {
Looper looper = getLooper();
if (looper != null) {
looper.quit();
return true;
}
return false;
}
/**
* 消息队列中剩余消息全部处理完毕后,退出线程的消息循环(安全退出循环)
*/
public boolean quitSafely() {
Looper looper = getLooper();
if (looper != null) {
looper.quitSafely();
return true;
}
return false;
}
/**
* Returns the identifier of this thread. See Process.myTid().
*/
public int getThreadId() {
return mTid;
}
}
注释已经很清楚了,不再重复说明各个方法的含义。
总结:HandlerThread在线程内部创建Looper和消息队列,并且在线程启动之后开启消息循环。我们可以使用该Looper构建Handler对象从而绑定工作线程,然后通过Handler向消息队列发送消息,这样HandlerThread就可以取出消息并根据消息类型执行具体的后台任务。由于HandlerThread的run方法是一个无限循环,因此当我们不再使用HandlerThread的时候应该调用它的quit或quitSafely方法来终止线程,这样可以节约系统资源。
二、使用方法
现在我们知道了HandlerThread的工作原理,接下来我们来看看HandlerThread的使用步骤:
private HandlerThread handlerThread; //工作线程
private Handler handler; //通知线程执行消息
//1. 创建HandlerThread实例
handlerThread = new HandlerThread("HT");
//2. 启动工作线程(启动消息循环系统)
handlerThread.start();
//3. 使用工作线程的Looper创建Handler,切换到工作线程处理后台任务
handler = new Handler(handlerThread.getLooper()) {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
try {
Thread.sleep(2000); //模拟耗时任务
} catch (InterruptedException e) {
e.printStackTrace();
}
int anInt = new Random().nextInt(1000);
LogUtils.d("更新UI:" + anInt);
}
};
//4. 发送消息通知handlerThread执行耗时任务
handler.sendEmptyMessage(0);
//5. 任务完成后停止线程释放资源
handlerThread.quit();
以上就是HandlerThread的使用步骤,它在Android中的一个典型的使用场景就是IntentService,感兴趣的话可以点击下面的链接,看看HandlerThread在IntentService中扮演者什么样的角色。
Android IntentService使用方法和源码分析
参考
《Android开发艺术探索》
转载于:https://www.jianshu.com/p/c041567e4dfc