一、前言
HandlerThread 是什么,其实就是一个Thread子类,然后里面开启了一个Looper循环来处理handler 发送的消息。
为什么会有HandlerThread,我们都知道如果在子线程直接创建使用handler会报错,提示没有looper。我们必须自己调用
Looper.prepare()创建当前线程的Looper对象、Looper.loop()开启消息循环。不懂的可以看我另一篇文章:
https://blog.youkuaiyun.com/qq_32650001/article/details/99829747 安卓消息机制
但是这种方式太不人性化了,于是谷歌推出了HandlerThread ,里面自动Lopper 我们就可以愉快的在子线程里使用handler了。
二、HandlerThread的基本使用
大致分为6步:
1、创建 HandlerThread对象
HandlerThread handlerThread = new HandlerThread("download")
2、开启线程(为什么这个时候开启线程等会源码分析说)
handlerThread.start()
3、 构建循环消息处理机制(运行在子程序中)
class ChildCallback implements Handler.Callback {
@Override
public boolean handleMessage(Message msg) {
mUIHandler.sendMessage(msg1);
//一般是主线程创建的handler对象去更新ui,mUIHandler的创建我没体现
return false;
}
}
4、创建绑定子线程的Handler对象
Handler childHandler = new Handler(handlerThread.getLooper(),new ChildCallback());
记住我们handlerThread.getLooper() 传入了子线程的Looper对象,此时改handler和子线程绑定到一起
5、子线程handler发送消息
childHandler.sendxxx(msg)
6、结束线程,即停止线程的消息循环
handlerThread.quit();
三、HandlerThread的源码分析
HandlerThread源码很少,我们一起看看吧~
public class HandlerThread extends Thread {
int mPriority;
int mTid = -1;
Looper mLooper;//Looper对象
private @Nullable Handler mHandler;
public HandlerThread(String name) {
super(name);
mPriority = Process.THREAD_PRIORITY_DEFAULT;
}
public HandlerThread(String name, int priority) {
super(name);
mPriority = priority;
}
protected void onLooperPrepared() {
}
/**
* 上面我说了要先start,开启线程
* 是因为开启线程后,会回调到run方法
* 来创建我们的Looper对象并开启循环
*/
@Override
public void run() {
mTid = Process.myTid();
Looper.prepare();//创建当前线程的Looper的对象
synchronized (this) {
mLooper = Looper.myLooper();//获取当前线程的Looper对象
notifyAll();//发送通知
}
Process.setThreadPriority(mPriority);
onLooperPrepared();
Looper.loop();//开启循环
mTid = -1;
}
/**
* 还记得我们在代码中getLooper获取
* 子线程的Looper给handler吧,你肯定会说
* 如果Looper对象还没创建成功呢,我获取啥哦
* 没事人家谷歌处理好了,请看~
*
*/
public Looper getLooper() {
if (!isAlive()) {
return null;
}
synchronized (this) {
while (isAlive() && mLooper == null) {//如果当前Looper为null
try {
wait()//等待,上面Looper创建好后会发送通知
} catch (InterruptedException e) {
}
}
}
return mLooper;
}
@NonNull
public Handler getThreadHandler() {
if (mHandler == null) {
mHandler = new Handler(getLooper());
}
return mHandler;
}
/**
* 其实就是清空了MessageQueue中的消息
*/
public boolean quit() {
Looper looper = getLooper();
if (looper != null) {
looper.quit();
return true;
}
return false;
}
/**
* 先判断是否有正在处理的消息,有就处理,然后在清空MessageQueue中的消息
*/
public boolean quitSafely() {
Looper looper = getLooper();
if (looper != null) {
looper.quitSafely();
return true;
}
return false;
}
public int getThreadId() {
return mTid;
}
}
四、总结:
上面分析了HandlerThread的使用和它的源码分析,算是比较清晰了,如果有什么不懂的地方欢迎给我留言,拜~