1、HandlerThread基本使用
在之前的《Android--掌握Handler、Looper、MessageQueue的基友关系》,我们写过一个实现Main线程给子线程发送消息的方法,没有看过的可以去上面的文章再看一下。下面我们使用另一种方式即:通过HandlerThread来实现Main线程给子线程发送消息:
private HandlerThread mHandlerThread;
private Handler mThreadHandler;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_handler_intent);
initHandler();
mThreadHandler.sendEmptyMessage(0);
L.D("发送消息及所在线程:" + Thread.currentThread());
}
private void initHandler() {
mHandlerThread = new HandlerThread("thc_test");
mHandlerThread.start();
mThreadHandler = new Handler(mHandlerThread.getLooper()){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
L.D("收到消息及所在线程" + Thread.currentThread());
}
};
}
打印的日志如下:
发送消息及所在线程:Thread[main,5,main]
收到消息及所在线程Thread[thc_test,5,main]说明发送成功了。
//停止从MessageQueue中取出消息
public void stop(){
mHandlerThread.quit();
}
结论
可以看到,这里我们不用再自己进行初始化一个Looper,而是直接使用了HandlerThread中初始化的Looper(即:通过HandlerThread.getLooper()方法获得Looper),其实在HandlerThread中初始化Looper也是和我们自己初始化的方式一样,只不过多了一些判断处理等。
2、HandlerThread源码及应用场景使用
mHandlerThread = new HandlerThread("thc_test");
mHandlerThread.start();
HandlerThread的使用就像我们使用普通的线程,new一个Thread,然后调用它的start方法启动线程。去看HandlerThread的源码,它继承Thread,就要重写它的run()方法,但是它的run()方法有些不同:
@Override
public void run() {
mTid = Process.myTid();
//先new一个Looper set到 ThreadLocal对应线程的副本中
Looper.prepare();
synchronized (this) {
//从ThreadLocal中取出该Looper
mLooper = Looper.myLooper();
notifyAll();
}
Process.setThreadPriority(mPriority);
onLooperPrepared();
//轮询当前线程MessageQueue中的消息
Looper.loop();
mTid = -1;
}
从上面注释也可以看出,在run()方法中,先得到一个Looper.prepare()得到一个Looper,然后进入一个同步方法(后面再说为什么要对这个方法进行同步处理),然后开始Looper.loop进行不断的轮询从MessageQueue中取出消息。
接下来,初始化在Handler:
mThreadHandler = new Handler(mHandlerThread.getLooper()){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
L.D("收到消息及所在线程" + Thread.currentThread());
}
};
先看一下mHandlerThread.getLooper()这个方法:
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;
}
mLooper是HandlerThread的成员变量,在run()方法中的同步方法中赋值。这里的getLooper其实就是获取这个mLooper。
总结:
一个Thread对应一个Looper和一个MssageQueue,而这个Looper在哪个线程初始化,那么这个Looper和MessagQueue就属于该线程,同时由该Looper作为构造参数初始化的Handler处理的也是该线程的消息。所以,如果我们想实现主线程控制子线程去操作的时候就使用HandlerThread可以了。
为什么使用同步方法呢:Looper和Handler两个实例的初始化分别是在两个线程中,为了解决这两个线程的同步问题。当mLooper == null的时候就wait,等待run方法中给mLooper赋值,赋值成功之后Handler才会创建成功,然后发送、处理的消息都是该线程的Looper取出和压入栈中的消息。