首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

Android 消息屏障与异步消息

Android 消息机制中的 MessageQueue 可以存放三种类型的消息,普通消息、消息屏障和异步消息。其中消息屏障和异步消息搭配使用,可以达到屏蔽普通消息、优先处理异步消息的目的。

「目录:」

如何插入一个消息屏障?

如何删除一个消息屏障?

如何插入一个异步消息?

消息屏障对插入消息有什么影响?

消息屏障是如何优先处理异步消息的?

Framework 中哪里使用了消息屏障?

1. 如何插入一个消息屏障?

见 MessageQueue 的 postSyncBarrier 方法:

消息屏障不需分发处理,没有 target Handler,后续也会根据有无 target 来判断是否为消息屏障

消息屏障也是有时间戳的,并且只会对后面的消息起到屏障作用,不会影响前面的消息

消息屏障插入后无需唤醒线程,因为消息屏障原本的目的就是打算屏蔽消息处理的

插入后会返回一个 token,用于后续移除指定 token 的消息屏障

方法为 private,外部调用需反射

2. 如何删除一个消息屏障?

见 MessageQueue 的 removeSyncBarrier 方法:

根据无 target 及 token 匹配找到对应的消息屏障

删除屏障后可能需要唤醒线程,是否唤醒取决于当前是否是因为消息屏障而阻塞的

3. 如何插入一个异步消息?

Message 的 setAsynchronous 为开放 API,直接调用设置即可,比如在 ViewRootImpl 中对输入事件的处理:

由于输入事件需要快速响应,优先级比较高,所以设置为异步消息,避免被消息屏障屏蔽掉

4. 消息屏障对插入消息有什么影响?

见 MessageQueue 的 enqueueMessage 方法:

如果插入到队列头部,那么只要当前线程是休眠的,就要唤醒,不管有没有消息屏障,因为消息屏障不会影响在它之前的消息

如果插入到队列中间且队列头消息为消息屏障,那还要判断插入的消息是不是最早的异步消息,如果是才唤醒线程。因为如果之前已经有异步消息,那说明已经对之前的异步消息做过唤醒或休眠指定时间的处理了,不用再此唤醒

5. 消息屏障是如何优先处理异步消息的?

见 MessageQueue 的 next 方法:

如果当前消息不是消息屏障,那异步消息和普通消息无异,都会按照时间排序依次执行

如果当前消息为消息屏障,就会去找队列中的异步消息,如果没有异步消息,就无限休眠;如果有,就根据这个异步消息的处理时间去分发处理或休眠

6. Framework 中哪里使用了消息屏障?

ViewRootImpl 中界面绘制时使用了消息屏障:

与输入事件一样,界面绘制也是优先级高的消息,需要优先处理,所以这里插入消息屏障 block 其他普通消息,以达到优先处理界面绘制的目的。

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20201102A01ZYY00?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券