EventBus 核心原理其实保存这三张图就可以弄懂了,收藏一下
思考
1、为什么要将注册监听对象作为 key,监听事件列表作为 value 放在 HashMap 中? 要弄懂一个问题,EventBus 是观察者模式,上面的 activity 也就是 subscribe 是订阅者,activity 中的 event 是订阅事件,一个订阅者可以订阅多个事件,移除一个订阅者的监听事件时,应该将其中所有的 event 的事件移除。 也就是说在反注册的时候,会通过 Subsribe 来查找到其中所有额 event 进行反注册。
2、第二幅图(订阅事件和订阅者)
这种表关系是 event 和 subsciption 的对应关系,比如在 Android 中多个 activity 可能会注册监听同一个 event 事件,所以在执行:
EventBus.getDefault().post(new Event1());
的时候所有注册监听了 Event1 的监听都会要会收到回调,看下 subsciption 的结构
subsciption 中包含,订阅的事件和订阅者本身,上面中所有的 event 就是订阅的事件,在 Android 中订阅的事件代码如下:
@Subscribe(threadMode = ThreadMode.MAIN)public void onEvent(Event event) {}
而 subsriber 就是订阅者比如会在 activity 的 onstart 中执行
....EventBus.getDefault().register(this);
那么 subsribe 就是 activity。
思考 为什么需要保存 Event 和 subsribe 对应的关系表?
这是因为一个 Event 可能会有被多个 subsribe 订阅,所以有当执行 post(Event)的时候会查找到所有订阅了 Event 事件的 subscribe 并调用其中的 event 方法。下面看下 post 方法:
private boolean postSingleEventForEventType(Object event, PostingThreadState postingState, Class<?> eventClass) {CopyOnWriteArrayList<Subscription> subscriptions;synchronized (this) {subscriptions = subscriptionsByEventType.get(eventClass);}if (subscriptions != null && !subscriptions.isEmpty()) {for (Subscription subscription : subscriptions) {postingState.event = event;postingState.subscription = subscription;boolean aborted = false;try {postToSubscription(subscription, event, postingState.isMainThread);aborted = postingState.canceled;} finally {postingState.event = null;postingState.subscription = null;postingState.canceled = false;}if (aborted) {break;}}return true;}return false;}}
post 和 postSticky 主要都会调用到上面的方法,上面方法中subscriptionsByEventType.get(eventClass)
就是通过 event 的类型找上面的表中找到对应的 subscriptions 进行通知的。
第三幅图
在看第三幅图之前思考一个问题,postSticky 到底是怎么执行的?为什么先执行 postSticky,后执行 register 还是可以监听到 event 事件? 先看 postSticky 代码:
public void postSticky(Object event) {synchronized (stickyEvents) {stickyEvents.put(event.getClass(), event);}// Should be posted after it is putted, in case the subscriber wants to remove immediatelypost(event);}复制代码
原来执行 postSticky 的时候会将 event.getclass 和 event 保存起来,然后再看下 subscribe 代码:
if (subscriberMethod.sticky) {if (eventInheritance) {// Existing sticky events of all subclasses of eventType have to be considered.// Note: Iterating over all events may be ineffici
ent with lots of sticky events,// thus data structure should be changed to allow a more efficient lookup// (e.g. an additional map storing sub classes of super classes: Class -> List<Class>).Set<Map.Entry<Class<?>, Object>> entries = stickyEvents.entrySet();for (Map.Entry<Class<?>, Object> entry : entries) {Class<?> candidateEventType = entry.getKey();if (eventType.isAssignableFrom(candidateEventType)) {Object stickyEvent = entry.getValue();checkPostStickyEventToSubscription(newSubscription, stickyEvent);}}} else {Object stickyEvent = stickyEvents.get(eventType);checkPostStickyEventToSubscription(newSubscription, stickyEvent);}
先判断注册监听的 event 是不是 sticky 的如果是就会用 stickEvents 表中找到 stickyEvent 如果如果注册的事件 event 和 stickyEvent 一样那么就会执行一次 postToSubscription 方法,也就是调用注册的方法执行。
总结
1、要理解 EventBus 就要从 register,unRegister,post,postSticky 方法入手。要理解 register 实质上是将订阅对象(比如 activity)中的每个带有 subscriber 的方法找出来,最后获得调用的就是这些方法。订阅对象(比如 activity)是一组 event 方法的持有者。
2、后注册的对象中 sticky 方法能够收到之前的 stickyEvent 方法的原因是 EventBus 中维护了 stickyEvent 的 hashMap 表,在 subsribe 注册的时候就遍历其中有没有注册监听 stickyEvent 如果有就会执行一次回调。
评论