消息分类
参考文章 Handler之消息屏障
消息可以分为三种
- 普通消息(同步)normal
- 屏障消息(同步)barrier
- 异步消息async
我们通常使用的都是普通消息,而屏障消息就是在消息队列中插入一个屏障,在屏障之后的所有普通消息都会被挡着,不能被处理。不过异步消息却例外,屏障不会挡住异步消息,因此可以这样认为:屏障消息就是为了确保异步消息的优先级,设置了屏障后,只能处理其后的异步消息,同步消息会被挡住,除非撤销屏障。
我们如何在消息队列中插入一个消息屏障?
postSyncBarrier()
需要注意6点:
- 这个消息是没有target的(handler);
- 也是带了时间戳的,只会影响它后面的消息;
- 一个消息队列是可以插入多个消息屏障的
- 消息屏障插到消息队列之后是没有唤醒消息线程的
- 插完屏障消息之后会返回一个token,是这个屏障的序列号,可用于之后需要撤除消息屏障时,通过token在消息队列查找
- postSyncBarrier()这个api是没有开放的,如果需要使用,只能通过反射调用(我们正常的enqueuemessage是会判断msg.target是否为null,是则会抛出异常)
@RequiresApi(api = Build.VERSION_CODES.M)
private void sendSyncBarrier() {
try {
MessageQueue queue = mHandler.getLooper().getQueue();
Method method = MessageQueue.class.getDeclaredMethod("postSyncBarrier");
method.setAccessible(true);
int token = (int) method.invoke(queue);
} catch (Exception e) {
e.printStackTrace();
}
}
删除屏障
从消息队列中删除,唤起线程
原理
引申出的几个问题:
1.消息队列是空的时候,插入一个屏障,会触发idleHandler吗?
答:不会。插入一个屏障,不会唤醒线程,无法进入到nativePollOnce之后的操作。
2.如果删除了屏障,消息队列空了,是否会触发idleHandler?
答:不会。