EventBus原理透析 ( 3.1.1 ) 带您更好的了解底层知识

Hey, do have a minute for a quick survey on how we are doing with EventBus?


yes.png

EventBus是一个开源库,
https://github.com/greenrobot/EventBus
主要通过发布者和订阅者来简化组件之间的通信,并解耦。

EventBus的优点?
1、简化组件之间的通信代码
2、分离事件发送者和接收者(解耦)
3、可以指定工作线程,可调整优先级
4、避免复杂且易出错的依赖关系和生命周期问题
5、速度快等

在使用的过程中会存在多个订阅者的情况,需要发送事件的同时打个标签,明确谁是谁的事件,使用场景过多后,如果标注不明确可能会导致后期维护增加阅读代码的难度。

使用方法直接进开源网址即可查看,文章主要是看看源码怎么写的。

EventBus分为三个部分:


官网图.png

1、Publisher发送者,通过post或postSticky 来发送消息。
2、Subscriber订阅者,register 或 unregister。
3、@Subscribe 注解 接收事件。

一、注册

EventBus.getDefault().register(this);

public static EventBus getDefault() {
        if (defaultInstance == null) {
            synchronized (EventBus.class) {
                if (defaultInstance == null) {
                    defaultInstance = new EventBus();
                }
            }
        }
        return defaultInstance;
    }

getDefault()进来之后,可以发现EventBus对象是个单例模式,这样就方便可以全局使用。保证了使用的是同一个对象。

  • 接着看下new EventBus,在初始EventBus的时候都初始了什么
public EventBus() {
        this(DEFAULT_BUILDER);
    }

    EventBus(EventBusBuilder builder) {
        logger = builder.getLogger();
        subscriptionsByEventType = new HashMap<>();
        typesBySubscriber = new HashMap<>();
        stickyEvents = new ConcurrentHashMap<>();
        mainThreadSupport = builder.getMainThreadSupport();
        mainThreadPoster = mainThreadSupport != null ? mainThreadSupport.createPoster(this) : null;
        backgroundPoster = new BackgroundPoster(this);
        asyncPoster = new AsyncPoster(this);
        indexCount = builder.subscriberInfoIndexes != null ? builder.subscriberInfoIndexes.size() : 0;
        subscriberMethodFinder = new SubscriberMethodFinder(builder.subscriberInfoIndexes,
                builder.strictMethodVerification, builder.ignoreGeneratedIndex);
        logSubscriberExceptions = builder.logSubscriberExceptions;
        logNoSubscriberMessages = builder.logNoSubscriberMessages;
        sendSubscriberExceptionEvent = builder.sendSubscriberExceptionEvent;
        sendNoSubscriberEvent = builder.sendNoSubscriberEvent;
        throwSubscriberException = builder.throwSubscriberException;
        eventInheritance = builder.eventInheritance;
        executorService = builder.executorService;
    }

构造方式是通过builder建造模式,除了builder模式之外,初始了很多的成员变量。

1、subscriptionsByEventType 这个hashmap贯穿整个EventBus,在subscriber方法中 是将订阅的事件都保存一份, 在post发送消息需要从它取,最后unregister的时候遍历移除一个个事件。
2、typesBySubscriber 这个hashmap 我觉得是跟subscriptionsByEventType差不多的,除了不涉及发送外。也是subscriber方法中保存订阅的事件,unregiste移除订阅事件。
3、stickyEvents 粘性事件处理的hashmap
4、SubscriberMethodFinder 主要是检验订阅事件的方法符合不符合EventBus的标准,不符合的都在内部throw做处理了。除了检验还加了双层效验,缓存等。但最终返回成一个List
5、参数尾部为Poster的,都是跟threadMode有关系的。
大致上就这些,先简单了解下作用,后面看源码的时候会很明确,至于没提到的后面可以看着理解。

  • 接着看register(),传入了一个Object对象。
public void register(Object subscriber) {
        Class subscriberClass = subscriber.getClass();
        List subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass);
        synchronized (this) {
            for (SubscriberMethod subscriberMethod : subscriberMethods) {
                subscribe(subscriber, subscriberMethod);
            }
        }
    }
  • 先看看 findSubscriberMethods
private static final Map, List> METHOD_CACHE = new ConcurrentHashMap<>();
···
List findSubscriberMethods(Class subscriberClass) {
        List subscriberMethods = METHOD_CACHE.get(subscriberClass);
        if (subscriberMethods != null) {
            return subscriberMethods;
        }

        if (ignoreGeneratedIndex) {
            subscriberMethods = findUsingReflection(subscriberClass);
        } else {
            subscriberMethods = findUsingInfo(subscriberClass);
        }
        if (subscriberMethods.isEmpty()) {
            throw new EventBusException("Subscriber " + subscriberClass
                    + " and its super classes have no public methods with the @Subscribe annotation");
        } else {
            METHOD_CACHE.put(subscriberClass, subscriberMethods);
            return subscriberMethods;
        }
    }
···
static void clearCaches() {
        METHOD_CACHE.clear();
    }

1、METHOD_CACHE就是一个缓存的map,首先从缓存里面找,缓存有直接就返回了,没有的话通过反射找,找完了缓存里面put存一份。
2、ignoreGeneratedIndex 在初始化SubscriberMethodFinder的时候,就传入这个参数了,全局代码没有地方修改,也没有默认设置为true,所以它如果在不手动设置的前提下,就一直是false。

  • 直接看false调用的方法
private List findUsingInfo(Class subscriberClass) {
        FindState findState = prepareFindState();
        findState.initForSubscriber(subscriberClass);
        while (findState.clazz != null) {
            findState.subscriberInfo = getSubscriberInfo(findState);
            if (findState.subscriberInfo != null) {
                SubscriberMethod[] array = findState.subscriberInfo.getSubscriberMethods();
                for (SubscriberMethod subscriberMethod : array) {
                    if (findState.checkAdd(subscriberMethod.method, subscriberMethod.eventType)) {
                        findState.subscriberMethods.add(subscriberMethod);
                    }
                }
            } else {
                findUsingReflectionInSingleClass(findState);
            }
            findState.moveToSuperclass();
        }
        return getMethodsAndRelease(findState);
    }

1、prepareFindState 会返回一个FindState对象, 这个类可以理解为辅助类,也可以理解为过渡类, 通过它过渡生成一个新的List后,将它内部的所有过渡成员变量都回收。它内部核心是 二层检查。
2、findState.subscriberInfo返回为null的,走else。

*接着看findUsingReflectionInSingleClass方法

private void findUsingReflectionInSingleClass(FindState findState) {
        Method[] methods;
        try {
            // This is faster than getMethods, especially when subscribers are fat classes like Activities
            methods = findState.clazz.getDeclaredMethods();
        } catch (Throwable th) {
            // Workaround for java.lang.NoClassDefFoundError, see https://github.com/greenrobot/EventBus/issues/149
            methods = findState.clazz.getMethods();
            findState.skipSuperClasses = true;
        }
        for (Method method : methods) {
            int modifiers = method.getModifiers();
            if ((modifiers & Modifier.PUBLIC) != 0 && (modifiers & MODIFIERS_IGNORE) == 0) {
                Class[] parameterTypes = method.getParameterTypes();
                if (parameterTypes.length == 1) {
                    Subscribe subscribeAnnotation = method.getAnnotation(Subscribe.class);
                    if (subscribeAnnotation != null) {
                        Class eventType = parameterTypes[0];
                        if (findState.checkAdd(method, eventType)) {
                            ThreadMode threadMode = subscribeAnnotation.threadMode();
                            findState.subscriberMethods.add(new SubscriberMethod(method, eventType, threadMode,
                                    subscribeAnnotation.priority(), subscribeAnnotation.sticky()));
                        }
                    }
                } else if (strictMethodVerification && method.isAnnotationPresent(Subscribe.class)) {
                    String methodName = method.getDeclaringClass().getName() + "." + method.getName();
                    throw new EventBusException("@Subscribe method " + methodName +
                            "must have exactly 1 parameter but has " + parameterTypes.length);
                }
            } else if (strictMethodVerification && method.isAnnotationPresent(Subscribe.class)) {
                String methodName = method.getDeclaringClass().getName() + "." + method.getName();
                throw new EventBusException(methodName +
                        " is a illegal @Subscribe method: must be public, non-static, and non-abstract");
            }
        }
    }

1、前面的代码就是 通过反射获取method[] ,遍历数组
2、getModifiers()获取这个类修饰符的整数,通过这个整数判定接收事件的方法,只能是public,且不能是abstract、static关键字。并且该方法也只能是一个参数。
3、method.getAnnotation(Subscribe.class);获取方法中 是否有Subscribe注解,有的话返回注解对象,没有的话返回的Null。

  • 这块有二层检查,看方法
boolean checkAdd(Method method, Class eventType) {
            // 2 level check: 1st level with event type only (fast), 2nd level with complete signature when required.
            // Usually a subscriber doesn't have methods listening to the same event type.
            Object existing = anyMethodByEventType.put(eventType, method);
            if (existing == null) {
                return true;
            } else {
                if (existing instanceof Method) {
                    if (!checkAddWithMethodSignature((Method) existing, eventType)) {
                        // Paranoia check
                        throw new IllegalStateException();
                    }
                    // Put any non-Method object to "consume" the existing Method
                    anyMethodByEventType.put(eventType, this);
                }
                return checkAddWithMethodSignature(method, eventType);
            }
        }


 private boolean checkAddWithMethodSignature(Method method, Class eventType) {
            methodKeyBuilder.setLength(0);
            methodKeyBuilder.append(method.getName());
            methodKeyBuilder.append('>').append(eventType.getName());

            String methodKey = methodKeyBuilder.toString();
            Class methodClass = method.getDeclaringClass();
            Class methodClassOld = subscriberClassByMethodKey.put(methodKey, methodClass);
            if (methodClassOld == null || methodClassOld.isAssignableFrom(methodClass)) {
                // Only add if not already found in a sub class
                return true;
            } else {
                // Revert the put, old class is further down the class hierarchy
                subscriberClassByMethodKey.put(methodKey, methodClassOld);
                return false;
            }
        }

1、这两个check方法都是findstate这个类的。
2、第一层检查,anyMethodByEventType.put()这个方法返回的是 key映射的旧值,如果没有则返回为null,也就是说之前没有别的方法订阅这个事件。没有直接返回true。
3、第二层检查,拼接methodKey、获取methodClass,传值给subscriberClassByMethodKey,获取methodClassOld,如果methodClassOld为null直接返回true,如果不为空,判定methodClassOld是否是methodClass的父类或者说是否是同一个类,如果都不满足,则当前方法不会被添加。

  • 检查通过后
if (findState.checkAdd(method, eventType)) {
  ThreadMode threadMode = subscribeAnnotation.threadMode();
  findState.subscriberMethods.add(new SubscriberMethod(method, eventType, threadMode,
  subscribeAnnotation.priority(), subscribeAnnotation.sticky()));
 }

1、获取注解上标注的类型, threadMode、sticky、priority跟着一起传入SubscriberMethod对象,并由findState.subscriberMethods.add填入。

  • 接着看下一步
private List getMethodsAndRelease(FindState findState) {
        List subscriberMethods = new ArrayList<>(findState.subscriberMethods);
        findState.recycle();
        synchronized (FIND_STATE_POOL) {
            for (int i = 0; i < POOL_SIZE; i++) {
                if (FIND_STATE_POOL[i] == null) {
                    FIND_STATE_POOL[i] = findState;
                    break;
                }
            }
        }
        return subscriberMethods;
    }

到这里就是获取了订阅者中的所有符合标准的订阅方法 的List, findState也是在这里进行回收,所以就更明确了findState 就是一个辅助类。

  • 回到register方法, 看subscribe
public void register(Object subscriber) {
        Class subscriberClass = subscriber.getClass();
        List subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass);
        synchronized (this) {
            for (SubscriberMethod subscriberMethod : subscriberMethods) {
                subscribe(subscriber, subscriberMethod);
            }
        }
    }


// Must be called in synchronized block
    private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) {
        Class eventType = subscriberMethod.eventType;
        Subscription newSubscription = new Subscription(subscriber, subscriberMethod);
        CopyOnWriteArrayList subscriptions = subscriptionsByEventType.get(eventType);
        if (subscriptions == null) {
            subscriptions = new CopyOnWriteArrayList<>();
            subscriptionsByEventType.put(eventType, subscriptions);
        } else {
            if (subscriptions.contains(newSubscription)) {
                throw new EventBusException("Subscriber " + subscriber.getClass() + " already registered to event "
                        + eventType);
            }
        }

        int size = subscriptions.size();
        for (int i = 0; i <= size; i++) {
            if (i == size || subscriberMethod.priority > subscriptions.get(i).subscriberMethod.priority) {
                subscriptions.add(i, newSubscription);
                break;
            }
        }

        List> subscribedEvents = typesBySubscriber.get(subscriber);
        if (subscribedEvents == null) {
            subscribedEvents = new ArrayList<>();
            typesBySubscriber.put(subscriber, subscribedEvents);
        }
        subscribedEvents.add(eventType);

        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).
                Set, Object>> entries = stickyEvents.entrySet();
                for (Map.Entry, 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);
            }
        }
    }

1、通过subscriber 和 subscriberMethod生成一个新的对象Subscription,subscriptionsByEventType通过eventType获取之前有没有value,没有的话就新建value,放到Key里。有的话就看看是不是已经被注册过事件。之后的代码逻辑都差不多,先判定符合后添加到对应的map里。
2、typesBySubscriber 和 subscriptionsByEventType我从最开始就简单的介绍了穿插的方法,现在可以发现确实如此。
3、粘性事件后面说,这块光知道粘性事件的开启是 获取注解时sticky = true

到此订阅的部分源码就讲完了,总结一下

1.内部有缓存
2.通过反射的方式 配合FindState辅助类,来判定订阅方法是否符合EventBus标准
3.被@Subscribe标注的订阅方法必须是public,不能有abstract、static 且 必须只能有一个参数
4.二层检查,检查订阅事件是否有方法监听,检查底层声明类与旧值底层声明类是否是父类关系,是否是同一个对象,旧值是否为空。

二、Post

注册完成后,订阅者与订阅方法都已存在,现在我们看发送者。
看这块的原因是想知道发送者怎么把事件发送给订阅方法的。

/** Posts the given event to the event bus. */
    public void post(Object event) {
        PostingThreadState postingState = currentPostingThreadState.get();
        List eventQueue = postingState.eventQueue;
        eventQueue.add(event);

        if (!postingState.isPosting) {
            postingState.isMainThread = isMainThread();
            postingState.isPosting = true;
            if (postingState.canceled) {
                throw new EventBusException("Internal error. Abort state was not reset");
            }
            try {
                while (!eventQueue.isEmpty()) {
                    postSingleEvent(eventQueue.remove(0), postingState);
                }
            } finally {
                postingState.isPosting = false;
                postingState.isMainThread = false;
            }
        }
    }
 
 

1、通过ThreadLocal获取一个PostingThreadState类的对象,接着就是对这个类里面的声明的一些成员变量进行赋值,核心还是看postSingleEvent方法。

private void postSingleEvent(Object event, PostingThreadState postingState) throws Error {
        Class eventClass = event.getClass();
        boolean subscriptionFound = false;
        if (eventInheritance) {
            List> eventTypes = lookupAllEventTypes(eventClass);
            int countTypes = eventTypes.size();
            for (int h = 0; h < countTypes; h++) {
                Class clazz = eventTypes.get(h);
                subscriptionFound |= postSingleEventForEventType(event, postingState, clazz);
            }
        } else {
            subscriptionFound = postSingleEventForEventType(event, postingState, eventClass);
        }
        if (!subscriptionFound) {
            if (logNoSubscriberMessages) {
                logger.log(Level.FINE, "No subscribers registered for event " + eventClass);
            }
            if (sendNoSubscriberEvent && eventClass != NoSubscriberEvent.class &&
                    eventClass != SubscriberExceptionEvent.class) {
                post(new NoSubscriberEvent(this, event));
            }
        }
    }

private static List> lookupAllEventTypes(Class eventClass) {
        synchronized (eventTypesCache) {
            List> eventTypes = eventTypesCache.get(eventClass);
            if (eventTypes == null) {
                eventTypes = new ArrayList<>();
                Class clazz = eventClass;
                while (clazz != null) {
                    eventTypes.add(clazz);
                    addInterfaces(eventTypes, clazz.getInterfaces());
                    clazz = clazz.getSuperclass();
                }
                eventTypesCache.put(eventClass, eventTypes);
            }
            return eventTypes;
        }
    }

1、eventInheritance参数是个开关,默认为true,开启后会通过lookupAllEventTypes,找到所有父类的事件并且存到List中,最后在通过postSingleEventForEventType来对事件进行处理。

  • postSingleEventForEventType方法
private boolean postSingleEventForEventType(Object event, PostingThreadState postingState, Class eventClass) {
        CopyOnWriteArrayList 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;
    }

1、在这个方法中通过subscriptionsByEventType取出之前赋值的所有subscriptions,通过postToSubscription对事件进行分发。这块加synchronized是因为hashmap线程是不安全的,此处分发需要线程同步。

  • postToSubscription方法
private void postToSubscription(Subscription subscription, Object event, boolean isMainThread) {
        switch (subscription.subscriberMethod.threadMode) {
            case POSTING:
                invokeSubscriber(subscription, event);
                break;
            case MAIN:
                if (isMainThread) {
                    invokeSubscriber(subscription, event);
                } else {
                    mainThreadPoster.enqueue(subscription, event);
                }
                break;
            case MAIN_ORDERED:
                if (mainThreadPoster != null) {
                    mainThreadPoster.enqueue(subscription, event);
                } else {
                    // temporary: technically not correct as poster not decoupled from subscriber
                    invokeSubscriber(subscription, event);
                }
                break;
            case BACKGROUND:
                if (isMainThread) {
                    backgroundPoster.enqueue(subscription, event);
                } else {
                    invokeSubscriber(subscription, event);
                }
                break;
            case ASYNC:
                asyncPoster.enqueue(subscription, event);
                break;
            default:
                throw new IllegalStateException("Unknown thread mode: " + subscription.subscriberMethod.threadMode);
        }
    }

1、这里的swtich很明确了,就是最开始订阅注解里的 threadMode。
2、invokeSubscriber是通过反射把事件传给订阅方法。
3、mainThreadPoster就是把线程切换成主线程,在调用invokeSubscriber。
4、backgroundPoster就是把线程切换成子线程,在子线程中调用invokeSubscriber。
5、asyncPoster就是把线程切换成子线程,在子线程中调用invokeSubscriber。

有了上面的5点基础理论,大概就清楚这几种模式都是什么情况?

  • POSTING
case POSTING:
                invokeSubscriber(subscription, event);
                break;

直接调用的invokeSubscriber,很明显就是post是什么线程,订阅事件处理就在什么线程。

  • MAIN
case MAIN:
                if (isMainThread) {
                    invokeSubscriber(subscription, event);
                } else {
                    mainThreadPoster.enqueue(subscription, event);
                }
                break;

如果在主线程,就在主线程处理订阅事件,如果不在主线程,就把事件对象传到队列中,发送一个message,由handlermessage来处理。
这块可以先看最开始EventBus初始化的那一堆成员变量里,其中有个MainThreadSupport,下面我摘出了核心代码。

EventBus(EventBusBuilder builder) {
        mainThreadSupport = builder.getMainThreadSupport();
}
···
MainThreadSupport getMainThreadSupport() {
        if (mainThreadSupport != null) {
            return mainThreadSupport;
        } else if (Logger.AndroidLogger.isAndroidLogAvailable()) {
            Object looperOrNull = getAndroidMainLooperOrNull();
            return looperOrNull == null ? null :
                    new MainThreadSupport.AndroidHandlerMainThreadSupport((Looper) looperOrNull);
        } else {
            return null;
        }
    }
···
Object getAndroidMainLooperOrNull() {
        try {
            return Looper.getMainLooper();
        } catch (RuntimeException e) {
            // Not really a functional Android (e.g. "Stub!" maven dependencies)
            return null;
        }
    }
···
class AndroidHandlerMainThreadSupport implements MainThreadSupport {

        private final Looper looper;

        public AndroidHandlerMainThreadSupport(Looper looper) {
            this.looper = looper;
        }

        @Override
        public boolean isMainThread() {
            return looper == Looper.myLooper();
        }

        @Override
        public Poster createPoster(EventBus eventBus) {
            return new HandlerPoster(eventBus, looper, 10);
        }
    }
···
public class HandlerPoster extends Handler implements Poster {

这很明显了,从AndroidHandlerMainThreadSupport方法传入的时候,就传入的是主线的loop。知道这点之后,case main也没别的什么了,就是handler接收消息后进行处理,处理就是invokeSubscriber。

  • MAIN_ORDERED
case MAIN_ORDERED:
                if (mainThreadPoster != null) {
                    mainThreadPoster.enqueue(subscription, event);
                } else {
                    // temporary: technically not correct as poster not decoupled from subscriber
                    invokeSubscriber(subscription, event);
                }
                break;

post在什么线程就在什么线程处理。

  • BACKGROUND
case BACKGROUND:
                if (isMainThread) {
                    backgroundPoster.enqueue(subscription, event);
                } else {
                    invokeSubscriber(subscription, event);
                }
                break;

final class BackgroundPoster implements Runnable, Poster {
···
private final static ExecutorService DEFAULT_EXECUTOR_SERVICE = Executors.newCachedThreadPool();
···
public void enqueue(Subscription subscription, Object event) {
        PendingPost pendingPost = PendingPost.obtainPendingPost(subscription, event);
        synchronized (this) {
            queue.enqueue(pendingPost);
            if (!executorRunning) {
                executorRunning = true;
                eventBus.getExecutorService().execute(this);
            }
        }
    }

@Override
    public void run() {
        try {
            try {
                while (true) {
                    PendingPost pendingPost = queue.poll(1000);
                    if (pendingPost == null) {
                        synchronized (this) {
                            // Check again, this time in synchronized
                            pendingPost = queue.poll();
                            if (pendingPost == null) {
                                executorRunning = false;
                                return;
                            }
                        }
                    }
                    eventBus.invokeSubscriber(pendingPost);
                }
            } catch (InterruptedException e) {
                eventBus.getLogger().log(Level.WARNING, Thread.currentThread().getName() + " was interruppted", e);
            }
        } finally {
            executorRunning = false;
        }
    }

我把主要的代码抠了出来,可以明确的看到backgroundPoster就是个Runnable,通过cache线程池调度,最后在run方法里进行事件处理。

  • ASYNC
    这个同理 跟BACKGROUND一样,也是由cache线程池调度,最后在run方法里进行事件处理。

unregister

public synchronized void unregister(Object subscriber) {
        List> subscribedTypes = typesBySubscriber.get(subscriber);
        if (subscribedTypes != null) {
            for (Class eventType : subscribedTypes) {
                unsubscribeByEventType(subscriber, eventType);
            }
            typesBySubscriber.remove(subscriber);
        } else {
            logger.log(Level.WARNING, "Subscriber to unregister was not registered before: " + subscriber.getClass());
        }
    }

private void unsubscribeByEventType(Object subscriber, Class eventType) {
        List subscriptions = subscriptionsByEventType.get(eventType);
        if (subscriptions != null) {
            int size = subscriptions.size();
            for (int i = 0; i < size; i++) {
                Subscription subscription = subscriptions.get(i);
                if (subscription.subscriber == subscriber) {
                    subscription.active = false;
                    subscriptions.remove(i);
                    i--;
                    size--;
                }
            }
        }
    }

这块没什么好说的,就是把之前添加过的事件,订阅都移除掉。
可以发现subscriptionsByEventType 与 typesBySubscriber 都是最开始subscribe的时候就存值了。

粘性事件

EventBus.getDefault().postSticky(this);

粘性事件从开始register->subscribe的时候,就开始post了

 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).
                Set, Object>> entries = stickyEvents.entrySet();
                for (Map.Entry, 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);
            }
        }
    }

···
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,与post一模一样,改变了它的调用顺序后,就使得它具有了粘性。在register的时候会post一次,在postSticky的时候也会调用一次。所以才会使得 先postSticky之后在注册,能接收到事件。

结束,
上述代码都是个人的理解,有问题可以留言。

你可能感兴趣的:(EventBus原理透析 ( 3.1.1 ) 带您更好的了解底层知识)