HandlerThread 是 Thread 的子类,严格意义上来说就是一个线程,其内部包含一个 Looper,通过这个 Looper 可以创建 Handler。
以下是 HandlerThread 的源码:
/**
* A Thread that has a Looper. The Looper can then be used to create Handlers.
*/
public class HandlerThread extends Thread {
int mPriority;
int mTid = -1;
Looper mLooper;
private @Nullable Handler mHandler;
@Override
public void run() {
mTid = Process.myTid();
Looper.prepare(); // 1
synchronized (this) {
mLooper = Looper.myLooper();
notifyAll();
}
Process.setThreadPriority(mPriority);
onLooperPrepared();
Looper.loop(); // 2
mTid = -1;
}
public Looper getLooper() {
if (!isAlive()) {
return null;
}
boolean wasInterrupted = false;
synchronized (this) {
while (isAlive() && mLooper == null) {
try {
wait();
} catch (InterruptedException e) {
wasInterrupted = true;
}
}
}
if (wasInterrupted) {
Thread.currentThread().interrupt();
}
return mLooper;
}
@NonNull
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;
}
}
从源码中可以看出,与普通的 Thread 相比,HandlerThread 多了一个 Looper,在 HandlerThread.run() 方法中,会调用 Looper.prepare() 来实现当前线程 Looper 的初始化,并调用 Looper.loop() 方法来启动 Looper 的循环。在 HandlerThread.quit()/HandlerThread.quitSafely() 方法中,调用了 Looper.quit()/Looper.quitSafely() 方法,主要是针对消息队列中是否还有消息或者延迟发送的消息还没有处理的情况。
下面看一下 HandlerThread 的用法。我们知道,如果在子线程中创建 Handler 是需要指定 Looper 的:
new Thread(() -> {
Looper.prepare();
Handler handler = new Handler(Looper.myLooper()) {
@Override
public void handleMessage(@NonNull Message msg) {
super.handleMessage(msg);
}
};
Looper.loop();
}).start();
上面的代码为子线程创建了 Looper,并且开启了 Looper 轮询(也可以直接使用主线程的 Looper)。在子线程中创建Looper,如果忘记了调用 Looper.prepare(),在运行代码的时候会报错:
if (mLooper == null) {
throw new RuntimeException(
"Can't create handler inside thread " + Thread.currentThread()
+ " that has not called Looper.prepare()");
}
为了避免繁琐的创建过程,可以使用 HandlerThread:
HandlerThread handlerThread = new HandlerThread("handler-thread");
handlerThread.start();
Handler handler = new Handler(handlerThread.getLooper()){
@Override
public void handleMessage(@NonNull Message msg) {
super.handleMessage(msg);
}
};
HandlerThread 中 Looper 的存在的意义如下:
- 方便获取线程 Looper;
- 保证了线程安全,一般在 Thread 里面,线程 Looper 进行初始化的代码里面,必须要调用 Looper.prepare() 和 Loop.loop();
new Thread(new Runnable() {
@Override
public void run() {
Looper.prepare();
Looper.loop();
}
});
参考
Android HandlerThread的用法
HandlerThread解析
Thread、Handler和HandlerThread关系何在?