EventBus 源码学习之粘性事件发布

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/shayubuhuifei/article/details/84620631

内容摘要

  • 猜想:粘性事件作为事件的一种特殊形式,他的大部分流程和普通事件都是一样的,但是是如何做到保证消息的送达呢?是在最后的发送部分有区别么?

    下面开始证明猜想是否正确呢?

详细内容

我们还是从入口的方法开始分析了吧,下面开始看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() 方法,将事件发布出去。这也就是你先发布了粘性事件的时候类还没有初始化,但是当类初始化后还能收到事件的原因。

是不是有点小惊喜原来还能这么干?但是这么做的也会产生问题,如果页面多次初始化,你会消费掉多个粘性事件。所以我们需要在我们消费掉粘性事件后 ,手动去做一次粘性事件的移除。

结束啦

有问题欢迎纠正,谢谢啦

如果对你有帮助就点个赞把,你的鼓励是我前进的动力。

猜你喜欢

转载自blog.csdn.net/shayubuhuifei/article/details/84620631