我们知道在线程里面创建Handler需要先调用Looper.prepare()创建looper,最后调用Looper.loop()开启循环,使用示例代码如下:
new Thread(){
@Override
public void run() {
Looper.prepare();
handler = new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
}
};
Looper.loop();
}
}.start();
一不小心忘记创建了looper可能会报错,或者忘记开启了消息队列的循环可能导致消息不能得到处理,有没有把这些都封装好的接口可供我们调用呢,这就是我们今天要讲的HandlerThread。我们先看看HandlerThread的使用方法:
HandlerThread handlerThread = new HandlerThread("test");
handlerThread.start();
handler = new Handler(handlerThread.getLooper());
}
public class HandlerThread extends Thread {
int mPriority;
int mTid = -1;
Looper mLooper;
private @Nullable Handler mHandler;
public HandlerThread(String name) {
super(name);
mPriority = Process.THREAD_PRIORITY_DEFAULT;
}
可以看到HandlerThread实际上是继承了Thread,等同于我们new Thread()而Thread又是实现了Runnable类:
public
class Thread implements Runnable {
/* Make sure registerNatives is the first thing does. */
/**
* The synchronization object responsible for this thread's join/sleep/park operations.
*/
private final Object lock = new Object();
/**
* Causes this thread to begin execution; the Java Virtual Machine
重点在这,调用了start(方法后系统会回调run方法)
* calls the run
method of this thread.
*
。。。。。。
public synchronized void start() {
// Android-changed: throw if 'started' is true
if (threadStatus != 0 || started)
throw new IllegalThreadStateException();
group.add(this);
started = false;
try {
nativeCreate(this, stackSize, daemon);
started = true;
} finally {
try {
if (!started) {
group.threadStartFailed(this);
}
} catch (Throwable ignore) {
/* do nothing. If start0 threw a Throwable then
it will be passed up the call stack */
}
}
}
从上面的注释可以看到系统会回调run方法,而HandlerThread继承了Thread且重写了run方法,所以最终回调执行的是HandlerThread里面的run方法,看下HandlerThread里面的run方法的实现:
@Override
public void run() {
mTid = Process.myTid();
//创建Looper
Looper.prepare();
synchronized (this) {
mLooper = Looper.myLooper();
notifyAll();
}
Process.setThreadPriority(mPriority);
onLooperPrepared();
//开启循环
Looper.loop();
mTid = -1;
}
可以看到之前需要自己手动操作的行为只要调用一下start,内部都给你封装好了,同时还提供了获取looper的方法,用于创建Handler的时候传入,因为此handler发出消息的执行是在UI线程还是工作线程执行就是取决于我们传入的Looper对象是在UI线程创建的还是在工作线程创建的,详细说明可以参考上面链接的Handler文章的相关知识:
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;
}
到此,应该可以看明白了,HandlerThread的工作原理其实和new Thread+Handler的相同,区别就是HandlerThread的使用更加友好,使用者不需要关注更多的内部实现细节,减少了使用的代价。