MessageQueue如何处理消息
Handler的这些方法最终执行的都是MessageQueue.enqueueMessage()
方法
1 | boolean enqueueMessage(Message msg, long when) { |
enqueueMessage()方法就是将handler发出的message插入messageQueue中。方法中走if条件的话就是当前queue中没有要处理的message,则当前插入的msg为message链表的头;如果走else方法,那么说明当前message链表中有message,插入的msg按照when的先后插入链表。
处理message链表中的消息是在Looper.loop()方法方法中进行的。loop()方法是个for(;;)循环,在每次循环中都会调用messageQueue.next()方法进行消息的获取,然后再分发处理。
messageQueue.next()
1 | Message next() { |
在next()方法的for循环里面
nativePollOnce(ptr, nextPollTimeoutMillis);
这句话nextPollTimeoutMillis=-1时会在native层阻塞,即message链表为空的情况(消息队列空闲)。当有消息立即执行或有消息将要执行都不会阻塞。
当阻塞在native层的时候,只有消息队列中插入了新的消息(messageQueue.enqueueMessage()
),才能唤醒nativePollOnce方法,再往下执行next方法。
消息队列优化
过滤重复消息
在
handler.sendMessage()
前,将之前发送过的相同what\object的message都remove掉。取消互斥消息
复用消息
复用消息可以避免重复GC
消息空闲IdleHandler
在消息队列空闲的时候会回调IdleHandler的queueIdle()方法。
idleHandler要在messageQueue中进行添加才能接收到回调。
Looper.myQueue().addIdleHandler(idleHandler)
使用独享的Looper——HandlerThread
在有Looper的线程就可以直接创建Handler,或者创建Handler的时候传入一个looper也可以。
delay大于Handler Looper的周期时,delay时间基本可靠
Looper负载越高,任务越容易积压,导致UI卡顿
在对时间要求高的时候,不要用Handler的delay作为计时的依据