HandlerThead原理及使用

简介

HandlerThread本质上是一个Thread,其内部增加了Looper和Handler。所以可以理解为一个原生SDK中封装好的一个异步类。能利用它执行耗时任务,并且通过内部的handler与其他线程进行通信。

1
2
3
4
5
6
7
8
9
10
11
12
13
public class HandlerThread extends Thread {
Looper mLooper;
private @Nullable Handler mHandler;
public HandlerThread(String name) {
// ... ...
mPriority = Process.THREAD_PRIORITY_DEFAULT;
}

@Override
public void run() {
// ... ...
}
}

简单使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// 步骤1:创建HandlerThread实例对象,创建线程
HandlerThread mHandlerThread = new HandlerThread("handlerThread");

// 步骤2:启动线程
mHandlerThread.start();

// 步骤3:创建工作线程Handler & 复写handleMessage()
// 该handler是与HandlerThread关联的。与主线程的handler无关联
Handler workHandler = new Handler( handlerThread.getLooper() ) {
@Override
public boolean handleMessage(Message msg) {
...//消息处理,执行异步任务,再通过主线程的handler与主线程进行通信
return true;
}
});

// 步骤4:使用工作线程Handler向工作线程的消息队列发送消息
// 在工作线程中,当消息循环时取出对应消息 & 在工作线程执行相关操作
// a. 定义要发送的消息
Message msg = Message.obtain();
msg.what = 2; //消息的标识
msg.obj = "Helloword"; // 消息的存放
// b. 通过Handler发送消息到其绑定的消息队列
workHandler.sendMessage(msg);

// 步骤5:结束线程,停止线程的消息循环
mHandlerThread.quit();

源码解析

当调用HandlerThread.start()的时候,会调用HandlerThead的run方法:
HandlerThead.class:

1
2
3
4
5
6
7
8
9
10
11
12
13
@Override
public void run() {
mTid = Process.myTid();
Looper.prepare();//创建Looper
synchronized (this) {
mLooper = Looper.myLooper();
notifyAll();//通知,looper已经创建好
}
Process.setThreadPriority(mPriority);//设置优先级
onLooperPrepared();
Looper.loop();//开始循环
mTid = -1;
}

当开始关联工作线程与handler的时候:Handler workHandler = new Handler( handlerThread.getLooper() ),会调用handlerThread.getLooper()方法获取looper

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public Looper getLooper() {
if (!isAlive()) {
return null;
}

// 如果线程已经开启,并且looper已经创建就返回looper,否则就已知等待。
synchronized (this) {
while (isAlive() && mLooper == null) {
try {
wait();
} catch (InterruptedException e) {
}
}
}
return mLooper;
}

当需要结束线程,停止循环的时候,需要HandlerThread.quit();

1
2
3
4
5
6
7
8
public boolean quit() {
Looper looper = getLooper();
if (looper != null) {
looper.quit();
return true;
}
return false;
}

总结

从上面可以看出,HandlerThread不会自动停止,所以需要手动调用HandlerThread.quit()来停止loop循环。

面试题:
工作线程如何创建使用Handler?