听说过消息屏障吗?
消息队列:单链表
消息类型:
normal,
barrier(屏障), block其他消息
async,相比normal多设置了一个异步标志位
如何想消息队列里插入屏障
屏障没有target(handler),因为不需要分发
也带了时间戳,插入队列时是按时间来排序,它只会影响它后面的消息
消息队列可插入多个屏障的
屏障插入消息队列后,没有唤醒线程去唤醒消息队列
插入屏障后会返回一个token(序列号),这个序列号用于后面撤除这个屏障用的
这个postSyncBarrier是private方法,只能通过反射调用, 手动插入一个没有target的消息进入队列会报错“message must have a target”
删除屏障后会唤醒线程(注意:添加屏障时没有唤醒线程)
获取消息时有屏障如何处理
nativePollOnce返回(唤醒线程)的3中情况:1:出错了,2: 超时了,消息的触发时间到了,3:有可读事件了
屏障只会block后面的normal消息,不能block后面的异步消息
插入消息时队列里有屏障会怎么处理
问题
1. 消息队列是空的时候,插一个屏障,会触发IdleHandler吗?
插入屏障不会唤醒线程(删除会),也就不会触发Idlehandler
2. 如果删除了屏障,消息队列空了,会触发IdleHandler吗?
不会,IdleHandler已经被调用过了,不会再重复触发。处理完一条消息后,如果队列里没有消息了,就会触发idleHandler,处理完idlehandler后,再看队列里是否有消息,如果还是没有的话,这时线程进入休眠,不会再调用idlehandler, 如果有别的线程唤醒了这个线程,会再去检查队列是否为空,为空的话,是不会再触发这个idlehandler的。
3. 如果消息队列只有一个屏障消息,插入一个普通消息会idleHandler吗?
有可能,IdleHandler的触发逻辑:消息队列是空或第一条消息的触发时间还没到才会执行IdleHandler,所以关键是这个屏障的触发时间到了没有
4. 如果消息队列只有一个屏障消息,插入一个异步消息会idleHandler吗?
有可能,IdleHandler的触发逻辑:消息队列是空或第一条消息的触发时间还没到才会执行IdleHandler,所以关键是这个屏障的触发时间到了没有
framework里哪些地方用到了屏障
scheduleTraversals会先插入一个屏障,block后面新的普通消息
当下一次VSync信号来时,执行mTraversalRunnable(调用doTraversal),删除屏障,优先执行异步消息performTraversal
demo,代码见资料
添加屏障
删除屏障
发送异步消息
总结
消息屏障:往队列里插入一个屏障,block住后面新的普通消息,主要是为了给异步消息开一个绿色通道,让其优先执行,比如UI绘制
异步消息:UI绘制,输入事件分发等,这些消息都是比较紧急的,不能被普通消息耽误了
网友评论