详解之前要说明一下,LivedataBus 比EventBus更适合目前jetpack化的app,因为考虑到组件的生命周期处理,性能方面,EventBus还是要反射invoke的调用的,网上找不到有实测过的博文,我想来个性能对比实测,然后写一篇博文分享给大家,想看的可以评论留言,我看看有多少人支持。想了解LiveDataBus的小伙伴可以看我这篇文章:Livedata和LivedataBus源码详解,那为什么还要分析EventBus,因为经典永不过时,里面的思想技巧还是值得学习的。
好了步入正题,整个框架运用了多个设计模式:首先从Eventbus的使用入手Eventbus.getDefault()方法,使用了带volatile的双重检验的单例模式,是线程安全的。这是
下 图中第一处,第二处开始使用了Builder模式
下图是具体的builder模式
然后就是register方法了,看下图中,根据订阅者对象找到它的有@Subsribe注解的方法集合,然后for循环调用subscribe订阅的方法。
我们看一下findSubscriberMethods下图中1是先从缓存中取,然后再是2,如果ignoreGeneratedIndex=true 通过反射来取,false的时候就通过index来取,最后是3数据入缓存,给下次使用。
我们重点看一下通过index 取的方法findUsinginfo,如下图,调用了getSubscriberInfo方法
沿着这条线,我们找到了subscriberInfoIndexes
它是一个list数据结构,而且只有通过SubscriberMethodFinder的构造方法赋值。
然后我们找到构造方法赋值的地方,哦用的是EventbusBuilder的 subscriberInfoIndexes
而它又是由addindex方法来添加item的。
下图注意是EventbusPerformance里面是在使用EventBus,看一下这个MyEventIndex
这里是apt+javapoet 技术编译生成的java类,代码就是index数据集。那这个名字是在哪指定生成的,我们接着看
在这指定的哦。
然后我们看看apt 中的注解处理器吧,现在都换成增量编译注解处理器了,减少了编译时间。
下图是javapoet 写入java文件中的操作。
这里需要注意一下, private final Map<Class<?>, CopyOnWriteArrayList> subscriptionsByEventType; 这个数据类型,先
放一个空的CopyOnWriteArrayList ,然后再这个CopyOnWriteArrayList里面填充数据,数据订阅完成。粘性事件的单拉出来一个map stickyEvents 使用
订阅的方法看完了,我们看一下post 发布消息的方法,注意下图的细节,用list eventQueue 实际上是currentPostingThreadState.get(). eventQueue 来缓存,这样多个调用这个post的方法的时候就不存在同步的问题,性能上得到了提升。
下图中又使用了 eventTypesCache map来缓存,这种手法前面说过就不说了,然后是enventinheritance 这是继承事件控制的,感兴趣的可以看看,就是你post这个类如果有子类,接口等的情况的,核心代码还是在postSingleEventForEventType里面
接下来的代码就没那么绕了
不同的线程里面 invoke ,所以我说最后还是会反射invoke一下。
反射中的耗时大概比例我查过了,如下图,也就是说EventBus 的 apt+javapoet 生成的index 代替了反射大部分耗时,但不完全invoke还是有的。
整个看下来 EventBus 是采用了观察者模式, 作者命名的时候更偏向发布/订阅者模式,我觉得这个命名会更贴切库本身方法的功能意义,可以笼统的认为这两个是别名的关系 ,但如果像网上说的发布订阅者模式强调中间调度者的话,这里严格的说是观察者模式。