内容摘要
-
猜想:粘性事件作为事件的一种特殊形式,他的大部分流程和普通事件都是一样的,但是是如何做到保证消息的送达呢?是在最后的发送部分有区别么?
下面开始证明猜想是否正确呢?
详细内容
我们还是从入口的方法开始分析了吧,下面开始看postSticky()方法:
public void postSticky(Object event) {
//把事件放到一个特定的粘性事件map中
synchronized (stickyEvents) {
stickyEvents.put(event.getClass(), event);
}
// Should be posted after it is putted, in case the subscriber wants to remove immediately
post(event);
}
就把粘性事件存了一下,就直接调用 post() 方法了?(手动滑稽)
这不应该啊,所以我还是在好好看看post的过程吧。找了一圈无果,这没道理啊?然后源码中搜索stickyEvents个map的使用的地方,然后找出了几处获取粘性事件和移除粘性事件的方法,但是明显这都不对,因为我们是找发送事件的地方,不是移除事件的地方。在找找?突然重点来了,在subscribe方法中出现了发送事件的代码。该方法是在类注册EventBus的时候调用的。
上面说了一堆,是不是明白了什么东西?下面看一下代码。
// Must be called in synchronized block
private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) {
//省略无关代码
if (subscriberMethod.sticky) {
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)) {
Object stickyEvent = entry.getValue();
checkPostStickyEventToSubscription(newSubscription, stickyEvent);
}
}
} else {
Object stickyEvent = stickyEvents.get(eventType);
checkPostStickyEventToSubscription(newSubscription, stickyEvent);
}
}
}
上面是EventBus 注册的部分代码,在注册的时候你会发现如果的粘性事件,有一些特殊的处理。
如果注册的是粘性事件的话,代码中会从stickyEvents中根据eventType取出事件,这个stickyEvents的map中的事件是在你调用postSticky() 方法后将事件存入到缓存的map中的。然后在注册的时候取出事件在进行发布。
checkPostStickyEventToSubscription() 方法。
private void checkPostStickyEventToSubscription(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());
}
}
上面方法中直接调用postToSubscription() 方法,将事件发布出去。这也就是你先发布了粘性事件的时候类还没有初始化,但是当类初始化后还能收到事件的原因。