*注:阅读本文需要具备基本的Handler基础
一、常见问题
HandlerThread是什么?
它是一个封装了Looper(Handler)机制的Thread。
它的应用场景是什么?
你可以将一些需要串行执行的子任务(耗时任务)交给它去做
二、简单使用
val handlerThread = HandlerThread("thread1")
handlerThread.start()
val looper = handlerThread.looper
var myHandler = object : Handler(looper){
override fun handleMessage(msg: Message) {
//这里是运行在handlerThread这个线程
Log.e("SSSS","handleMessage线程:"+Thread.currentThread().name)
// 处理耗时任务
}
}
myHandler.sendEmptyMessage(555)
Log.e("SSSS","sendEmptyMessage线程:"+Thread.currentThread().name)

三、源码分析
//创建HandlerThread对象hou,必须先调用start()来初始化Looper对象,并执行loop(),
//Looper机制的使用都是这个流程(可参考ActivityThread中Looper的使用)
public class HandlerThread extends Thread {
//设置优先级
int mPriority;
int mTid = -1;
//属于此线程的Looper,间接持有了只属于此线程的MessageQueue对象
Looper mLooper;
private @Nullable Handler mHandler;
// name:线程名
public HandlerThread(String name) {
super(name);
mPriority = Process.THREAD_PRIORITY_DEFAULT;
}
/**
* Constructs a HandlerThread.
* @param name 线程名
* @param priority 优先级
*/
public HandlerThread(String name, int priority) {
super(name);
mPriority = priority;
}
/**
* 在loop()执行前,需要运行的代码可以放在这里
*/
protected void onLooperPrepared() {
}
//调用start()后,run()开始执行
@Override
public void run() {
mTid = Process.myTid();
//初始化Looper、MessageQueue对象等
Looper.prepare();
//思考:这里加同步锁,是为了控制下面getLooper()中的同步代码块,同时只有一个地方能执行
// 为了保证getLooper()中返回的mLooper对象一定是赋值过的
synchronized (this) {
//notifyAll(); 此方法也可以写在这里效果一致,调用notifyAll()并不是马上唤醒wait()处挂起的代码
//而是整个同步块都执行完才会去唤醒
//用于对外暴露Looper对象
mLooper = Looper.myLooper();
notifyAll(); //写在这里更符合人们的思维逻辑
}
Process.setThreadPriority(mPriority);
onLooperPrepared();
//开启loop循环
Looper.loop();
mTid = -1;
}
/**
*
*
*
* @return 返回 looper 对象
*/
public Looper getLooper() {
// 判断当前线程是否存活
if (!isAlive()) {
return null;
}
boolean wasInterrupted = false;
// 如上面的使用案例中所示,此方法和 Thread.start()对应的run()不确定哪个先执行(因为在两个线程中),若run()
// 先执行mLooper已被赋值不为null,直接返回皆大欢喜。
// 如果是此方法先执行呢? mLooper=null,就需要调用wait(),挂起当前执行,释放对象锁,run()中的同步代码块就会
// 得到此对象锁,给mLooper进行赋值,赋值后调用notifyAll(),继续执行wait()后面的代码返回mLooper对象。
synchronized (this) {
while (isAlive() && mLooper == null) { //思考:为何用while 用if不行吗?
try {
wait();
} catch (InterruptedException e) {
wasInterrupted = true;
}
}
}
//对于要用while而不是if的原因可能是这样的,因为用户的行为是不可控的,假如用户也写了一个同步代码块:
/*
* synchronized (this) { //也用了此HandlerThread作为对象锁
* notifyAll(); //在其他地方调用notifyAll(),而不是run()中调用,上面的wait()也有可能被恢复
// 此时mLooper = null,返回就会有问题,而使用while可以解决此问题,当wait()恢复后
// 依然去检查 mLooper是否为空,若不为空,跳出while循环返回;若为空继续调用wait()挂起
// 继续等待为 mLooper赋值
* ...
* }
/*
* We may need to restore the thread's interrupted flag, because it may
* have been cleared above since we eat InterruptedExceptions
*/
if (wasInterrupted) {
Thread.currentThread().interrupt();
}
return mLooper;
}
/**
* @return a shared {@link Handler} associated with this thread
* @hide
*/
@NonNull
public Handler getThreadHandler() {
if (mHandler == null) {
mHandler = new Handler(getLooper());
}
return mHandler;
}
/**
* Quits the handler thread's looper.
* <p>
* Causes the handler thread's looper to terminate without processing any
* more messages in the message queue.
* </p><p>
* Any attempt to post messages to the queue after the looper is asked to quit will fail.
* For example, the {@link Handler#sendMessage(Message)} method will return false.
* </p><p class="note">
* Using this method may be unsafe because some messages may not be delivered
* before the looper terminates. Consider using {@link #quitSafely} instead to ensure
* that all pending work is completed in an orderly manner.
* </p>
*
* @return True if the looper looper has been asked to quit or false if the
* thread had not yet started running.
*
* @see #quitSafely
*/
public boolean quit() {
Looper looper = getLooper();
if (looper != null) {
looper.quit();
return true;
}
return false;
}
//安全退出looper循环
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;
}
}