Moosphan/Android-Daily-Interview

2019-10-29:谈一谈EventBus的原理?

MoJieBlog opened this issue · 5 comments

  • 如何实现通信
  • 如何实现粘性事件

观察者被观察者

EventBus1、 register方法将对象实例用软引用包裹,保存到一个map缓存集合中
2、post方法 传入一个对象进去,然后遍历map里面多有的对象,找到所有的带有 @subscribe注解的并且方法参数与post的对象是同一类型的Method。 并通过反射执行Method。
3、Subscribe线程调度 执行method方法的时候会去获取注解上标记得线程,然后切换到指定线程。4、unregister取消订阅 从第一步中的缓存map中移除对应注册的对象实例

直接说下eventbus3吧
发布订阅者模式
通过向 eventbus调度中心 注册
eventbus 中维护了三个map
1map<eventType,订阅信息集合>
2map<订阅者,eventype集合>
3.map<eventtype,事件> 用于维护粘性事件

注册的时候 会把信息填入 1,2 两个map, 而订阅信息是怎么获取的呢?
2种方式, 1.runtime注解, 通过反射机制获取 订阅者中被 注解标注的方法,然后 把类信息和方法信息存入map 2.编译时注解, eventbus3 提供了额外的 注解去处理器,可以在编译时生成索引,把类信息在编译时放入索引中.所以在event注册时去查找方法 会先从缓存中找,找不到就判断是否加入了索引,如果加入索引 就直接从索引中取,如果不支持索引,则通过反射机制,获取信息

2这个map适用于反注册的, 通过订阅者找到他的事件,然后移除
3.说一下粘性事件,通常 我们要先注册才能收到, 而粘性事件,则保留了这个事件最后一次的发出,即先发出在注册还能收到最后一次的事件,他通过一个 map 来维护 这个关系, 在注册时 查找方法之后,会从这个map中取出事件,然后执行.

另外eventbus支持 几种线程模式 posting main ordermain background asyc
分别是 原线程, 主线程 有序主线程 唯一后台线程 线程池

这里说下有序主线程 就是在 一个 被注解方法中发送另外一个eventbus
如果两个线程都是 ordermain 那么 一定会在 第一个方法回调执行完毕之后,才会去回调另外一个被注解的方法

register注册一个订阅者
获取注册类 通过注册类获取所有的事件订阅内容
遍历所有注册类的订阅内容 执行注册订阅
将我们的订阅方法和订阅者封装到subscriptionsByEventType分发事件集合和typesBySubscriber中
如果是粘性事件的话,就立马投递、执行

事件发送逻辑
获取到当前线程的事件队列
通过事件类型获取到所有订阅者集合
通过反射执行订阅者中的订阅方法

取消逻辑
1、首先通过unregister方法拿到要取消的订阅者
2、得到该订阅者的所有订阅事件类型
3、遍历事件类型,根据每个事件类型获取到所有的订阅者集合,并从集合中删除该订阅者
4、将订阅者从步骤2的集合中移除