源码基于 Android API 25
HandlerThread 相比于普通的 Thread,其内部会多维护一个 Looper,因此也多维护着一个消息队列,从而可以直接使用,而不用像普通的 Thread 那样,还要自己去处理 Looper。
然后通过 getLooper() 获取对应的 Looper,从而使用对应的 Handler。
public class HandlerThread extends Thread {
int mPriority;
int mTid = -1;
// 内部维护的 Looper
Looper mLooper;
public HandlerThread(String name) {
super(name);
mPriority = Process.THREAD_PRIORITY_DEFAULT;
}
public HandlerThread(String name, int priority) {
super(name);
mPriority = priority;
}
protected void onLooperPrepared() {}
@Override
public void run() {
mTid = Process.myTid();
// Looper.prepare() 会为当前线程实例化一个 Looper 并保存到 ThreadLocal 中,
// 但是如果 当前线程已经存在 Looper 了,再调用 Looper.prepare() 就会出异常
Looper.prepare();
synchronized (this) {
// 得到当前线程对应的 Looper 赋值给 mLooper
mLooper = Looper.myLooper();
// notifyAll() 是为了唤醒个 getLooper() 中的 wait()
notifyAll();
}
Process.setThreadPriority(mPriority);
// 在开启 loop 前调用 onLooperPrepared(),该方法可以重写,实现自己的逻辑
onLooperPrepared();
Looper.loop();
mTid = -1;
}
public Looper getLooper() {
if (!isAlive()) {
return null;
}
// If the thread has been started, wait until the looper has been created.
synchronized (this) {
// 如果线程是存活状态,但是 mLooper 还没有被初始化的话,则会阻塞住,直到 Looper 被创建
while (isAlive() && mLooper == null) {
try {
// 在 run() 中会执行 notifyAll()
wait();
} catch (InterruptedException e) {
}
}
}
return mLooper;
}
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;
}
public int getThreadId() {
return mTid;
}
}
其中,在 run() 方法中才会将当前线程维护的 Looper 实例化,并开始 Looper 的循环,也就说,不执行 Thread#start()
,就无法真正的在子线程中去启动 Looper。
而直接调用 run(),此时是处于调用线程中执行的,此时如果调用线程中已经存在 Looper 了,就会出现异常。
另外,通过 getLooper()
可以获取线程对应的 looper,但是前提是线程是存活状态,且 looper 已经被创建。否则,就会该方法就会陷入阻塞状态,直到 looper 被创建,或者线程已经处于非存活状态了。
当 HandlerThread 不要用了的时候,则需要通过 quit()/quitSafely()
来主动退出 Looper,从而终止线程。因此 Looper 在退出之前会处于无限循环状态,这样会导致线程也一直存活。