什么是 handler,looper,MessageQueue
- handler :消息的发送和处理器
- looper : 消息的传递器
- MessageQueue:消息存放队列
一个完整的消息传递流程
- 当我们调用new Handler()创建handler对象之后进行消息的发送
- 调用handler.sendMessage,或者sendMessageDelay等等,其实最终都会调用方法中我们都会看到其实是将消息放入消息队列enqueueMessage(queue, msg, uptimeMillis);
public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
MessageQueue queue = mQueue;
if (queue == null) {
RuntimeException e = new RuntimeException(
this + " sendMessageAtTime() called with no mQueue");
Log.w("Looper", e.getMessage(), e);
return false;
}
最终都会调用消息进入队列的方法
return enqueueMessage(queue, msg, uptimeMillis);
}
3.那么问题来了,消息队列,也就是这个MessageQueue哪里来的?
其实消息队列是在looper初始化的时候创建的,下面的代码是looper对象中的
private Looper(boolean quitAllowed) {
//在这里创建了消息的队列
mQueue = new MessageQueue(quitAllowed);
mThread = Thread.currentThread();
}
现在知道了消息队列是如何来的,这个looper对象什么时候创建的?
4.looper什么时候创建?:
- 当我们处于主线程的时候,主线程会主动调用looper.preper方法,贴上代码
private static void prepare(boolean quitAllowed) {
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
//重点是这一行代码,它调用了本地线程的工具类,创建looper对象加入这个工具类的静态成员中
sThreadLocal.set(new Looper(quitAllowed));
}
- 当我们处于子线程时,当前线程中不会主动创建looper对象,这也就是为什么当我们在子线程中new handler进行使用时会出现以下异常
java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
所以说当我们需要在子线程中new handler使用的时候需要先在当前子线程中调用looper.preper方法进行looper对象的创建,这样也才会创建属于当前子线程的MessageQueue否则发送到当前子线程的消息将无处存放,也就会出现上面的错误
5.looper.loop执行死循环等待消息
for (;;) {
//下面这行代码将是死循环,一直等待取消息
Message msg = queue.next(); // might block
if (msg == null) {
// No message indicates that the message queue is quitting.
return;
}
总结
- 执行的整个流程就是
线程调用looper.preper创建looper对象->looper对象创建消息队列MessageQueue用来存放消息
线程调用looper.loop循环取消息队列中的消息
创建handler,handler发送消息->消息进入消息队列
handler取消息->消息出队
网友评论