探究EventBus粘性事件实现机制


theme: juejin

highlight: a11y-light

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第3天,点击查看活动详情

  1. 粘性事件观察者

    1. @Subscribe(threadMode = ThreadMode.MAIN, sticky = true)
    2. fun registerEventBus(o: Any) {
    3. }
  2. 发送粘性事件

    1. EventBus.getDefault().postSticky(Any())
  3. 注册EventBus

    1. EventBus.getDefault().register(this)

接下来我们就来探究下EventBus的粘性事件是如何实现的。

postSticky()内部机制

image.png

  1. 如果是发送的粘性事件,会添加到stickyEvents中,看下这个属性的实现:

image.png
可以看到这个属性是一个Map集合,其中key为事件类型的class对象,value为对应的事件类型。

  1. 继续看下post(Event)方法:

image.png

  1. 首先将这个粘性事件添加到PostingThreadState(线程私有)的eventQueue集合中

  2. 通过isMainThread方法判断当前是否为主线程,最终会调用到我们熟悉的Looper.getMainLooper() == Looper.myLooper()进行判断

    1. 循环遍历eventQueue队列,不断的取出集合元素进行分发,看下postSinleEvent()方法如何实现:

image.png

  1. 如果eventInheritance为true,会查找当前发送的粘性事件类型的父类型,并返回查找到的集合

  2. 接下来就会调用postSingleEventForEventType()方法来进行最终粘性事件的分发,即通知通过@Subscribe注解注册的粘性事件观察者,看下具体实现:

image.png

  1. 调用subscriptionsByEventType获取注册该事件类型的所有订阅方法,但是由于这个时候我们是先发送的粘性事件再注册EventBus,而subscriptionsByEventType中集合元素的填充实在注册EventBus发生的,所以通过subscriptionsByEventType获取到的subscriptions将是null的,所以接下来肯定不会走下面的if代码块中的逻辑了。

postSticky()小结

上面这么多代码逻辑,其实只干了一件事,就是将这个粘性事件添加到了stickyEvents这个集合中。之后的逻辑虽多,但和粘性事件没啥关系。

register内部机制

image.png

  1. findSubscriberMethods()这个方法里面的逻辑就不带大家进行分析了,总之就干了一件事情:

    查找当前类通过@Subscribe注册的所有事件订阅方法,并返回一个List<SubscriberMethod>集合,其中SubscriberMethod就是对每个注册的订阅方法和当前注册类的封装

  2. subscribe这个方法是关键,深入探究下:

image.png

image.png

  • 第1、2、3、4步中其实就干了两件事情:

    • 填充subscriptionsByEventType集合,key为事件类型,value为通过@Subscribe订阅了该事件类型的方法集合
    • 填充typesBySubscriber集合,key为注册EventBus的类,value为该类中所有@Subscribe注解修饰的方法集合
  • 第5步就是实现粘性事件分发的关键地方

    • 首先判断当前@Subscribe修饰的订阅方法是否为粘性,即@Subscribe(sticky = true)sticky等于true
    • 是的话就从stickyEvents集合中判断是否存在和订阅方法中注册的事件类型相同的事件:

      这个stickyEvents是不是很熟悉,就是我们之前发送粘性事件时,将粘性事件添加到的方法集合

    • 如果存在,则就执行该粘性事件的分发,即调用执行该订阅方法,最终会调用到invokeSubscriber()方法:

image.png

从上面可以看到,最终是通过反射来实现的订阅了粘性事件方法的执行。

register小结

该方法最终会判断当前是否存在注册EventBus前发送的粘性事件,且当前注册类中存在订阅该事件类型的方法,然后立即执行。

总结

以上就是EventBus粘性事件的内部实现机制,总体来说不算复杂,大家看着文章跟着源码一步步分析应该就很容易理解这部分实现逻辑了。


文章标签:

原文连接:https://juejin.cn/post/7102815596621856799

相关推荐

Android多版本flavor配置之资源文件和清单文件合并介绍

Android 面试题:说一下 PendingIntent 和 Intent 的区别

Intent 跳转 传递list集合

Google Play 开发者账户被封 如何改代码快速上架

百度APP Android包体积优化实践(二)Dex行号优化

使用ComposeDesktop开发一款桌面端多功能APK工具

一年时间过去了,LiveData真的被Flow代替了吗? LiveData会被废弃吗?

Flutter 绘制探索 | 箭头端点的设计

Android Notes | 开发手记 ing...

Flutter 小技巧之优化使用的 BuildContext

Android原生自定义车牌输入法 附带两种实现思路以及源码 EasyVehicleKeyBoard

Dart(五)—泛型、库使用、async和await关键字

Android启动优化深入解析,全面掌握!

Android技术知识点:如何使用数据绑定来消除findViewById()

ExoPlayer客户端解密m3u8音频\u002F视频

第四届青训营阅读打卡活动来啦,奖品、规则全面升级,快来学习吧

视频直播小窗口(悬浮窗)展示方案

Flutter 2 商城App实战指南(支持Null safety)

LaunchedEffect到底为我们处理了什么问题?

Android View | Canvas详解