publicvoidpostSticky(Object event) { synchronized (stickyEvents) { stickyEvents.put(event.getClass(), event); } // Should be posted after it is putted, in case the subscriber wants to remove immediately post(event); }
postSticky 代码比较简单,首先对 stickyEvents 进行加锁,接下来把 event 事件的 Class 对象作为 Key,event 事件本身作为 value 放进 Map 中,其中stickyEvents 是 Map 对象,实例是 ConcurrentHashMap, 其 Key 和 Value 的泛型形参分别是 Class<?> 和 Object, 它的作用就是用来存储黏性事件;然后调用 post(event) 把黏性事件当作普通事件发送一下。
首先我们看下最后为什么要调用下 post(event)?
虽然 post(evnet) 上面有注释,简单翻译下:“在放进 Map 后应该再发送一次,以防止订阅者想立即删除此事件”,读完注释后,可能还是不太明白,这里笔者认为:在前面存储完黏性事件后,这里调用 post 把黏性事件当作普通事件发送出去,或许是因为现在已经有注册的黏性事件订阅者,此时把已经注册的黏性事件订阅者当作普通事件的订阅者,这样已经注册的黏性事件订阅者可以立即收到相应的事件,只是此时事件不再是黏性的。
// 接下来就是黏性事件的发送逻辑了 // 判断 Event 接收方法是否可以处理黏性事件 if (subscriberMethod.sticky) { // 这里判断是否考虑 Event 事件类的继承关系,默认为 Ture if (eventInheritance) { // Existing sticky events of all subclasses of eventType have to be considered. // Note: Iterating over all events may be inefficient 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)) { ObjectstickyEvent= entry.getValue(); checkPostStickyEventToSubscription(newSubscription, stickyEvent); } } } else { ObjectstickyEvent= stickyEvents.get(eventType); checkPostStickyEventToSubscription(newSubscription, stickyEvent); } } }
privatevoidcheckPostStickyEventToSubscription(Subscription newSubscription, Object stickyEvent) { if (stickyEvent != null) { // If the subscriber is trying to abort the event, it will fail (event is not tracked in posting state) // --> Strange corner case, which we don't take care of here. postToSubscription(newSubscription, stickyEvent, isMainThread()); } }
可能细心的读者已经发现 test 方法调用了,问题应该出在 postSticky 方法中,让我们再次查看 postSticky 方法:
1 2 3 4 5 6 7 8 9
privatefinal Map<Class<?>, Object> stickyEvents;
publicvoidpostSticky(Object event) { synchronized (stickyEvents) { stickyEvents.put(event.getClass(), event); } // Should be posted after it is putted, in case the subscriber wants to remove immediately post(event); }
根据前面分析 postSticky 方法的结果,stickyEvents 用于存储黏性事件,它是个 Map 结构,而 stickyEvents 的 Key 正是 Event 的 Class 对象,根据 Map 结构的存储原理:如果存在相同的 Key,则覆盖 Value 的值,而 stickyEvents 的 Value 正是 Event 本身。
/** * If true, delivers the most recent sticky event (posted with * {@link EventBus#postSticky(Object)}) to this subscriber (if event available). */ booleansticky()defaultfalse;
// 增加消息必达的方法 booleanrendezvous()defaultfalse;
/** Subscriber priority to influence the order of event delivery. * Within the same delivery thread ({@link ThreadMode}), higher priority subscribers will receive events before * others with a lower priority. The default priority is 0. Note: the priority does *NOT* affect the order of * delivery among subscribers with different {@link ThreadMode}s! */ intpriority()default0; }
publicvoidpostRendezvous(Object event) { synchronized (rendezvousEvents) { rendezvousEvents.add(Pair.create(event.getClass(), event)); } // Should be posted after it is putted, in case the subscriber wants to remove immediately post(event); }
上面的源码,我们通过仿照 postSticky 方法实现了 postRendezvous 方法,在 postSticky 方法中使用 Map 存储黏性事件,不过我们在 postRendezvous 方法中使用 List 存储必达事件,保证必达事件不会因为 Key 相同而被覆盖丢失,最后也是调用 post 方法尝试先发送一次必达事件。