- Handler 绑定在消息上
消息循环主要是不断取出消息,让Handler去处理消息,也就是说,Handler是消息发送端,和处理端。
下面来看一下循环消息部分源代码
private static boolean loopOnce(final Looper me,
final long ident, final int thresholdOverride) {
Message msg = me.mQueue.next(); // might block
if (msg == null) {
// No message indicates that the message queue is quitting.
return false;
}
//省略掉一些代码
try {
msg.target.dispatchMessage(msg);//从消息中,拿到Handler 引用
} catch (Exception exception) {
throw exception;
} finally {
}
msg.recycleUnchecked();
return true;
}
msg.target.dispatchMessage(msg);
target
就是消息绑定的handler
- MessageQueue 一个线程通常只有一个消息队列
prepare()
方法是绑定了线程和Looper的关系,也就是存储到线程上
private static void prepare(boolean quitAllowed) {
sThreadLocal.set(new Looper(quitAllowed));
}
然后在消息循环的时候,根据根据当前线程去取出Looper
public static void loop() {
final Looper me = myLooper();
//省略掉一些代码
for (;;) {
if (!loopOnce(me, ident, thresholdOverride)) {
return;
}
}
}
public static @Nullable Looper myLooper() {
return sThreadLocal.get();
}
然后消息队列MessageQueue
是在Looper初始化的时候就创建好了
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);
mThread = Thread.currentThread();
}
所以一个Thread
关联上了一个Looper
,Looper
关联上了MessageQueue
,循环的时候,通过Looper
拿到MessageQueue
,MessageQueue
不断去读取Message
,下面是循环方法loopOnce
,
Message msg = me.mQueue.next();
private static boolean loopOnce(final Looper me,
final long ident, final int thresholdOverride) {
Message msg = me.mQueue.next(); // might block
if (msg == null) {
// No message indicates that the message queue is quitting.
return false;
}
//省去一堆代码
msg.recycleUnchecked();
return true;
}
那是不是所有的线程自动就有这些关系?不是的,需要怎么做才行呢,源码给出了例子。
class LooperThread extends Thread {
public Handler mHandler;
public void run() {
Looper.prepare();//1
//2
mHandler = new Handler(Looper.myLooper()) {
public void handleMessage(Message msg) {
// process incoming messages here
}
};
//3
Looper.loop();
}
}
其实这么做,只是为了建立关系而已。当然Google也给了一个封装好的线程HandlerThread
- 频繁切换不同线程
当我们在后台线程执行过程中,突然又要切换到主线程执行,这时候就可以借助Handler这套消息机制,它可以帮忙我们在不同的线程之前切换。但是,如果反复在不同线程之间切换,代码实现起来经常会很难看,为了优化这个问题,很多开源工具就出现了,比如EventBus,RxJava.