cnmen / cnmen.github.io

4 stars 0 forks source link

事件总线框架EventBus,该升级啦! | 西门博客 - 让技术更透明、让开发更简单! #30

Open cnmen opened 5 years ago

cnmen commented 5 years ago

https://www.cmonbaby.com/posts/netease_eventbus.html

作者:彭老师 日期:2019-07-25 类型:Android 说明:本文源于彭老师手写摘要,如需转载请带上链接或注明出处! EventBus(最新版3.1.1)问题和修复: 1、发布粘性事件:触发了所有同类型订阅方法(粘性和非粘性),已修复 2、粘性事件订阅方法无法第2次消费(很难满足复杂项目要求),已修复 3、多次调用和移除粘性事件时,post会执行多次粘性事件订阅方法(非粘性正常

huangxiaojingCN commented 5 years ago

关于 “多次调用和移除粘性事件时,post会执行多次粘性事件订阅方法(非粘性正常)” ,问题应该是出现在源码 401 行 postSingleEventForEventType 方法里

private boolean postSingleEventForEventType(Object event, PostingThreadState postingState, Class<?> eventClass) {
        CopyOnWriteArrayList<Subscription> subscriptions;
        synchronized (this) {
            subscriptions = subscriptionsByEventType.get(eventClass);
        }
        if (subscriptions != null && !subscriptions.isEmpty()) {

           // 这里会把订阅事件的方法都调用,只要加入到了 subscriptionsByEventType  map 集合
            for (Subscription subscription : subscriptions) {

                Log.e("James", "postSingleEventForEventType subscription: " + subscription.subscriberMethod.methodString);
                postingState.event = event;
                postingState.subscription = subscription;
                boolean aborted = false;
                try {
                    // postToSubscription 被多次调用
                    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;
    }

导致问题出现的根本原因是在注册的时候,注册类中所有订阅事件方法会被封装为 Subscription 加入到 subscriptionsByEventType map 集合里,而 removeStickyEvent 并不会删除 subscriptionsByEventType 集合粘性事件的 Subscription。后续执行 post 发送事件就会出现上述方法 postSingleEventForEventType 中多次调用的问题。

cnmen commented 5 years ago

给楼上点个赞! 真人不露面,露面不真人!