美文网首页Android
EventBus源码解读

EventBus源码解读

作者: 几行代码 | 来源:发表于2019-02-17 14:31 被阅读75次

    上一篇中我们讲解了EventBus的使用,传送门:https://www.jianshu.com/p/1e624bf9144d
    这篇我们从源码出发一步一步解析EventBus实现原理。

    这里先列出一个大纲,接下来会大致根据这个大纲一步一步深入剖析:
    1.获取EventBus实例;
    2.注册订阅者;
    3.书写接收订阅事件的方法;
    4.发送事件给订阅者;
    5.注销;

    1.获取EventBus实例

    1)EventBus mEventBus = EventBus.getDefault();
    
    2)EventBus eventBus = EventBus.builder()
                    .logNoSubscriberMessages(false)
                    .sendNoSubscriberEvent(false)
                    .build();
    

    1)跟着源码进去:

    /**
         * Convenience singleton for apps using a process-wide EventBus instance.
         * 双重检查
         */
        public static EventBus getDefault() {
            if (defaultInstance == null) {
                synchronized (EventBus.class) {
                    if (defaultInstance == null) {
                        defaultInstance = new EventBus();
                    }
                }
            }
            return defaultInstance;
        }
    
    /**
         * Creates a new EventBus instance; each instance is a separate scope in which events are delivered. To use acentral bus, consider {@link #getDefault()}.
         * 创建一个新的 EventBus 实例,每个实例在 events 事件被发送的时候都是一个单独的领域,为了使用一个 事件总线,考虑用 getDefault() 构建。
         */
        public EventBus() {
            this(DEFAULT_BUILDER);
        }
    
    private static final EventBusBuilder DEFAULT_BUILDER = new EventBusBuilder();
    

    单例模式,后面我会单独抽出一篇来说,这里略过。

    这里来看看EventBus的成员变量及构造函数:

    • 成员变量:
    static volatile EventBus defaultInstance; // 单例采用 volatile 修饰符,会降低性能,但能保证EventBus每次取值都是从主内存中读取
    
        private static final EventBusBuilder DEFAULT_BUILDER = new EventBusBuilder();
    
        // 发送 post 事件的 map 缓存
        private static final Map<Class<?>, List<Class<?>>> eventTypesCache = new HashMap<>();
    
        // key 为事件类型,value为封装订阅者和订阅方法的对象的集合
        private final Map<Class<?>, CopyOnWriteArrayList<Subscription>> subscriptionsByEventType;
    
        // key为订阅者,value为eventType的List集合,用来存放订阅者中的事件类型
        private final Map<Object, List<Class<?>>> typesBySubscriber;
    
        //key为 eventType(事件类型对象的字节码),value为发送的事件对象
        private final Map<Class<?>, Object> stickyEvents; // 黏性事件
    
        // currentPostingThreadState
        private final ThreadLocal<PostingThreadState> currentPostingThreadState = new ThreadLocal<PostingThreadState>() {
            @Override
            protected PostingThreadState initialValue() {
                return new PostingThreadState();
            }
        };
    
        // @Nullable
        private final MainThreadSupport mainThreadSupport;  // 用于线程间调度
        // @Nullable  主线程中的 poster
        private final Poster mainThreadPoster;
    
        // 后台线程中的 poster
        private final BackgroundPoster backgroundPoster;
    
        // 异步线程中的 poster
        private final AsyncPoster asyncPoster;
    
        private final SubscriberMethodFinder subscriberMethodFinder; // 对已经注解过的Method的查找器
    
        private final ExecutorService executorService;  // 线程池 Executors.newCachedThreadPool()
    
        private final boolean throwSubscriberException; // 是否需要抛出SubscriberException
        private final boolean logSubscriberExceptions; // 当调用事件处理函数发生异常是否需要打印Log
        private final boolean logNoSubscriberMessages; // 当没有订阅者订阅这个消息的时候是否打印Log
        private final boolean sendSubscriberExceptionEvent; // 当调用事件处理函数,如果异常,是否需要发送Subscriber这个事件
        private final boolean sendNoSubscriberEvent;  // 当没有事件处理函数时,对事件处理是否需要发送sendNoSubscriberEvent这个标志
        private final boolean eventInheritance;  // 与Event有继承关系的类是否都需要发送
    
        private final int indexCount; // 用于记录event生成索引
        private final Logger logger;
    

    PS:
    ThreadLocal是线程内部的存储类,通过它我们可以在指定的线程中存储数据,存储完只能在指定的线程中获取到数据,其他线程就无法获取到该线程的数据。

    • 构造函数:
    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);
    
            // 用于记录event生成索引
            indexCount = builder.subscriberInfoIndexes != null ? builder.subscriberInfoIndexes.size() : 0;
    
            // 对已经注解过的Method的查找器,会对所设定过 @Subscriber 注解的的方法查找相应的Event
            subscriberMethodFinder = new SubscriberMethodFinder(builder.subscriberInfoIndexes,
                    builder.strictMethodVerification, builder.ignoreGeneratedIndex);
    
            // 当调用事件处理函数发生异常是否需要打印Log
            logSubscriberExceptions = builder.logSubscriberExceptions;
    
            // 当没有订阅者订阅这个消息的时候是否打印Log
            logNoSubscriberMessages = builder.logNoSubscriberMessages;
    
            // 当调用事件处理函数,如果异常,是否需要发送Subscriber这个事件
            sendSubscriberExceptionEvent = builder.sendSubscriberExceptionEvent;
    
            // 当没有事件处理函数时,对事件处理是否需要发送sendNoSubscriberEvent这个标志
            sendNoSubscriberEvent = builder.sendNoSubscriberEvent;
    
            // 是否需要抛出SubscriberException
            throwSubscriberException = builder.throwSubscriberException;
    
            // 与Event有继承关系的类是否都需要发送
            eventInheritance = builder.eventInheritance;
    
            // 线程池 Executors.newCachedThreadPool()
            executorService = builder.executorService;
        }
    

    2)跟着源码进去

    public class EventBus {
       public static EventBusBuilder builder() {
              return new EventBusBuilder();
       }
    }
    
    public class EventBusBuilder {
       /**
         * Builds an EventBus based on the current configuration.
         * 基于当前配置生成事件总线
         */
        public EventBus build() {
            return new EventBus(this);
        }
    }
    

    可以看到这两种方法都是通过EventBusBuilder构造出来的。

    • EventBusBuilder:
    package org.greenrobot.eventbus;
    
    import android.os.Looper;
    
    import org.greenrobot.eventbus.meta.SubscriberInfoIndex;
    
    import java.util.ArrayList;
    import java.util.List;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    
    /**
     * Creates EventBus instances with custom parameters and also allows to install a custom default EventBus instance.
     * 使用自定义参数创建EventBus实例,并允许安装自定义默认EventBus实例
     * Create a new builder using {@link EventBus#builder()}.
     */
    public class EventBusBuilder {
    
        // 这个就是我们的线程池了,异步任务,后台任务就要靠它来执行了
        private final static ExecutorService DEFAULT_EXECUTOR_SERVICE = Executors.newCachedThreadPool();
    
        boolean logSubscriberExceptions = true;  //订阅者异常日志
        boolean logNoSubscriberMessages = true;  //不要订阅者消息日志
        boolean sendSubscriberExceptionEvent = true; //是否发送订阅者异常
        boolean sendNoSubscriberEvent = true;  //是否发送无订阅者异常
        boolean throwSubscriberException;  // 是否抛出订阅者异常
        boolean eventInheritance = true;   // 是否继承事件
        boolean ignoreGeneratedIndex;      // 是否忽略生成的索引
        boolean strictMethodVerification; // 是否严格执行方法验证
        ExecutorService executorService = DEFAULT_EXECUTOR_SERVICE; // 默认线程池
        List<Class<?>> skipMethodVerificationForClasses;   // 需要跳过执行方法验证的类
        List<SubscriberInfoIndex> subscriberInfoIndexes;   // 订阅者信息索引
        Logger logger;
        MainThreadSupport mainThreadSupport;
    
        EventBusBuilder() {
        }
    
        /**
         * Default: true  订阅者异常日志,默认打印
         */
        public EventBusBuilder logSubscriberExceptions(boolean logSubscriberExceptions) {
            this.logSubscriberExceptions = logSubscriberExceptions;
            return this;
        }
    
        /**
         * Default: true  不要订阅者消息日志
         */
        public EventBusBuilder logNoSubscriberMessages(boolean logNoSubscriberMessages) {
            this.logNoSubscriberMessages = logNoSubscriberMessages;
            return this;
        }
    
        /**
         * Default: true   是否发送订阅者异常
         */
        public EventBusBuilder sendSubscriberExceptionEvent(boolean sendSubscriberExceptionEvent) {
            this.sendSubscriberExceptionEvent = sendSubscriberExceptionEvent;
            return this;
        }
    
        /**
         * Default: true  是否发送无订阅者异常
         */
        public EventBusBuilder sendNoSubscriberEvent(boolean sendNoSubscriberEvent) {
            this.sendNoSubscriberEvent = sendNoSubscriberEvent;
            return this;
        }
    
        /**
         * Fails if an subscriber throws an exception (default: false).
         * Tip: Use this with BuildConfig.DEBUG to let the app crash in DEBUG mode (only). This way, you won't miss
         * exceptions during development.
         * 使用buildconfig.debug可以使应用程序在调试模式下崩溃(仅限)。这样,您就不会错过开发过程中的异常。
         *
         * 是否抛出订阅者异常  默认为 false,可以在debug情况下设置为 true 进行调试
         */
        public EventBusBuilder throwSubscriberException(boolean throwSubscriberException) {
            this.throwSubscriberException = throwSubscriberException;
            return this;
        }
    
        /**
         * By default, EventBus considers the event class hierarchy (subscribers to super classes will be notified).
         * Switching this feature off will improve posting of events. For simple event classes extending Object directly,
         * we measured a speed up of 20% for event posting. For more complex event hierarchies, the speed up should be
         * >20%.
         * 默认情况下,EventBus考虑事件类层次结构(将通知父类的订户)。
         * 关闭此功能将改进事件发布。
         * 对于直接扩展对象的简单事件类,我们测量到事件发布的速度提高了20%。对于更复杂的事件层次结构,速度应大于20%
         * <p/>
         * However, keep in mind that event posting usually consumes just a small proportion of CPU time inside an app,
         * unless it is posting at high rates, e.g. hundreds/thousands of events per second.
         * 但是,请记住,事件发布通常只占用应用程序内部CPU时间的一小部分,除非它以高速率发布,例如每秒数百/数千个事件
         *
         * 是否继承事件,把这个功能关闭可以提高效率,默认为 true
         */
        public EventBusBuilder eventInheritance(boolean eventInheritance) {
            this.eventInheritance = eventInheritance;
            return this;
        }
    
    
        /**
         * Provide a custom thread pool to EventBus used for async and background event delivery. This is an advanced
         * setting to that can break things: ensure the given ExecutorService won't get stuck to avoid undefined behavior.
         * 为用于异步和后台事件传递的事件总线提供自定义线程池。
         * 这是一个高级设置,可以打断一些事件:确保给定的ExecutorService不会被卡住以避免未定义的行为
         */
        public EventBusBuilder executorService(ExecutorService executorService) {
            this.executorService = executorService;
            return this;
        }
    
        /**
         * Method name verification is done for methods starting with onEvent to avoid typos; using this method you can
         * exclude subscriber classes from this check. Also disables checks for method modifiers (public, not static nor
         * abstract).
         * 方法名验证是对以OnEvent开头的方法进行的,以避免出现错误;使用此方法,可以从该检查中排除订阅服务器类。
         * 还禁用对方法修饰符(公共、非静态或抽象)的检查
         */
        public EventBusBuilder skipMethodVerificationFor(Class<?> clazz) {
            if (skipMethodVerificationForClasses == null) {
                skipMethodVerificationForClasses = new ArrayList<>();
            }
            skipMethodVerificationForClasses.add(clazz);
            return this;
        }
    
        /**
         * Forces the use of reflection even if there's a generated index (default: false).
         * 强制使用反射,即使存在生成的索引(默认值:false)。
         * 使用索引可以大大提高效率
         */
        public EventBusBuilder ignoreGeneratedIndex(boolean ignoreGeneratedIndex) {
            this.ignoreGeneratedIndex = ignoreGeneratedIndex;
            return this;
        }
    
        /**
         * Enables strict method verification (default: false).
         * 启用严格的方法验证(默认值:false)
         */
        public EventBusBuilder strictMethodVerification(boolean strictMethodVerification) {
            this.strictMethodVerification = strictMethodVerification;
            return this;
        }
    
        /**
         * Adds an index generated by EventBus' annotation preprocessor.
         * 添加由EventBus的批注预处理器生成的索引,可以添加多个索引
         */
        public EventBusBuilder addIndex(SubscriberInfoIndex index) {
            if (subscriberInfoIndexes == null) {
                subscriberInfoIndexes = new ArrayList<>();
            }
            subscriberInfoIndexes.add(index);
            return this;
        }
    
        /**
         * Set a specific log handler for all EventBus logging. 为所有事件总线日志记录设置特定的日志处理程序。
         * <p/>
         * By default all logging is via {@link android.util.Log} but if you want to use EventBus
         * outside the Android environment then you will need to provide another log target.
         * 默认情况下,所有日志记录都是通过 android.util.log进行的,但如果您想在android环境之外使用eventbus,则需要提供另一个日志目标。
         */
        public EventBusBuilder logger(Logger logger) {
            this.logger = logger;
            return this;
        }
    
        Logger getLogger() {
            if (logger != null) {
                return logger;
            } else {
                // also check main looper to see if we have "good" Android classes (not Stubs etc.)
                return Logger.AndroidLogger.isAndroidLogAvailable() && getAndroidMainLooperOrNull() != null
                        ? new Logger.AndroidLogger("EventBus") :
                        new Logger.SystemOutLogger();
            }
        }
    
    
        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;
            }
        }
    
        /**
         * Installs the default EventBus returned by {@link EventBus#getDefault()} using this builders' values. Must be
         * done only once before the first usage of the default EventBus.
         * 使用此生成器的值安装 eventbus getdefault()返回的默认eventbus。在第一次使用默认事件总线之前只能执行一次
         * 所以在 Application 中执行
         * @throws EventBusException if there's already a default EventBus instance in place
         * 如果已经有了一个默认的eventbus实例,就抛出异常
         */
        public EventBus installDefaultEventBus() {
            synchronized (EventBus.class) {
                if (EventBus.defaultInstance != null) {
                    throw new EventBusException("Default instance already exists." +
                            " It may be only set once before it's used the first time to ensure consistent behavior.");
                }
                EventBus.defaultInstance = build();
                return EventBus.defaultInstance;
            }
        }
    
        /**
         * Builds an EventBus based on the current configuration.
         * 基于当前配置生成事件总线
         */
        public EventBus build() {
            return new EventBus(this);
        }
    }
    

    从上面可以看出通过 EventBusBuilder 这个类可以构建出我们想要的EventBus。
    注意点:installDefaultEventBus()方法的调用,使用这个方法生成的 EventBus,在第一次使用默认事件总线之前只能执行一次,所以在 Application 中执行,如果已经有了一个默认的eventbus实例,就抛出异常。

    2.注册订阅者

     EventBus eventBus = EventBus.builder().build();
     eventBus.register(this);
    
    • register方法:
    /**
         * 注册给定的订阅服务器以接收事件。一旦订户对接收事件不再感兴趣,他们必须调用 unregister(object)。
         * 订阅服务器具有必须由 subscribe 注释的事件处理方法。 subscribe注释还允许配置,如 threadMode 和优先级。
         *
         * 传进来的是订阅者 subscriber
         */
        public void register(Object subscriber) {
            // 通过反射获取到订阅者的对象
            Class<?> subscriberClass = subscriber.getClass();
    
            // 通过Class对象找到对应的订阅者方法集合
            List<SubscriberMethod> subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass);
    
            // 遍历订阅者方法集合,将订阅者和订阅者放方法想成订阅关系
            synchronized (this) {
                // 迭代每个 Subscribe 方法,调用 subscribe() 传入 subscriber(订阅者) 和 subscriberMethod(订阅方法) 完成订阅,
                for (SubscriberMethod subscriberMethod : subscriberMethods) {
                    subscribe(subscriber, subscriberMethod);
                }
            }
        }
    
    • private final SubscriberMethodFinder subscriberMethodFinder; // 对已经注解过的Method的查找器。
    • findSubscriberMethods方法:
    // 订阅方法的缓存,key为订阅者对象,value为订阅者对象所有的订阅方法是一个List集合
        private static final Map<Class<?>, List<SubscriberMethod>> METHOD_CACHE = new ConcurrentHashMap<>();
    
    /**
         * 订阅方法查找
         * @param subscriberClass 订阅者对象
         * @return 返回订阅者 所有的订阅方法 是一个List集合
         */
        List<SubscriberMethod> findSubscriberMethods(Class<?> subscriberClass) {
            // 首先在 METHOD_CACHE 中查找该 Event 对应的订阅者集合是否已经存在,如果有直接返回
            List<SubscriberMethod> subscriberMethods = METHOD_CACHE.get(subscriberClass);
            if (subscriberMethods != null) {
                return subscriberMethods;
            }
    
            // 根据订阅者类 subscriberClass 查找相应的订阅方法
            if (ignoreGeneratedIndex) { // 是否忽略生成 index 默认为 false,当为 true 时,表示以反射的方式获取订阅者中的订阅方法
                subscriberMethods = findUsingReflection(subscriberClass); // 通过反射获取
            } else {
                // 通过 SubscriberIndex 方式获取
                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); // 把订阅方法集合 List 存到缓存中
                return subscriberMethods;
            }
        }
    
    • findUsingReflection() 通过反射获取订阅方法集合 *** start ***
    private List<SubscriberMethod> findUsingReflection(Class<?> subscriberClass) {
            // 创建并初始化 FindState 对象
            FindState findState = prepareFindState();
    
            // findState 与 subscriberClass 关联
            findState.initForSubscriber(subscriberClass);
            while (findState.clazz != null) {
                // 使用反射的方式获取单个类的订阅方法
                findUsingReflectionInSingleClass(findState);
    
                // 使 findState.clazz 指向父类的 Class,继续获取
                findState.moveToSuperclass();
            }
    
            // 返回订阅者及其父类的订阅方法 List,并释放资源
            return getMethodsAndRelease(findState);
        }
    
    • prepareFindState()方法:
    class SubscriberMethodFinder {
        private static final int POOL_SIZE = 4;
        private static final FindState[] FIND_STATE_POOL = new FindState[POOL_SIZE];
    }
    
    // 通过 prepareFindState 获取到 FindState 对象
        private FindState prepareFindState() {
            // 找到 FIND_STATE_POOL 对象池
            synchronized (FIND_STATE_POOL) {
                for (int i = 0; i < POOL_SIZE; i++) {
                    // 当找到了对应的FindState
                    FindState state = FIND_STATE_POOL[i];
                    if (state != null) { // FindState 非空表示已经找到
                        FIND_STATE_POOL[i] = null; // 清空找到的这个FindState,为了下一次能接着复用这个FIND_STATE_POOL池
                        return state; // 返回该 FindState
                    }
                }
            }
    
            // 如果依然没找到,则创建一个新的 FindState
            return new FindState();
        }
    
    • FindState这是EventBus的一个静态内部类:
    // FindState 封装了所有的订阅者和订阅方法的集合
        static class FindState {
            // 保存所有订阅方法
            final List<SubscriberMethod> subscriberMethods = new ArrayList<>();
    
            // 事件类型为Key,订阅方法为Value
            final Map<Class, Object> anyMethodByEventType = new HashMap<>();
    
            // 订阅方法为Key,订阅者的Class对象为Value
            final Map<String, Class> subscriberClassByMethodKey = new HashMap<>();
    
            final StringBuilder methodKeyBuilder = new StringBuilder(128);
    
            Class<?> subscriberClass;
            Class<?> clazz;
            boolean skipSuperClasses;
            SubscriberInfo subscriberInfo;
    
            // findState 与 subscriberClass 关联
            void initForSubscriber(Class<?> subscriberClass) {
                this.subscriberClass = clazz = subscriberClass;
                skipSuperClasses = false;
                subscriberInfo = null;
            }
    
            void recycle() {
                subscriberMethods.clear();
                anyMethodByEventType.clear();
                subscriberClassByMethodKey.clear();
                methodKeyBuilder.setLength(0);
                subscriberClass = null;
                clazz = null;
                skipSuperClasses = false;
                subscriberInfo = null;
            }
    
    
            /**
             * EventBus 不仅仅获取当前类的订阅方法,还会获取它所有父类的订阅方法。
             *
             * 在 EventBus 中,一个订阅者包括这个订阅者的所有父类和子类,不会有多个方法相同的去接收同一个事件.
             * 但是有可能出现这样一种情况,子类去订阅了该事件,父类也去订阅了该事件。
             * 当出现这种情况,EventBus 如何判断?通过调用 checkAddWithMethodSignature() 方法,根据方法签名来检查
             */
            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.
                // put()方法执行之后,返回的是之前put的值
                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();
                // put方法返回的是put之前的对象
                Class<?> methodClassOld = subscriberClassByMethodKey.put(methodKey, methodClass);
    
                // 如果methodClassOld不存在或者是methodClassOld的父类的话,则表明是它的父类,直接返回true。
                // 否则,就表明在它的子类中也找到了相应的订阅,执行的 put 操作是一个 revert 操作,put 进去的是 methodClassOld,而不是 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
                    // 这里是一个revert操作,所以如果找到了它的子类也订阅了该方法,则不允许父类和子类都同时订阅该事件,put 的是之前的那个 methodClassOld,就是将以前的那个 methodClassOld 存入 HashMap 去覆盖相同的订阅者。
                    // 不允许出现一个订阅者有多个相同方法订阅同一个事件
                    subscriberClassByMethodKey.put(methodKey, methodClassOld);
                    return false;
                }
            }
    
            // 使 findState.clazz 指向父类的 Class,继续获取
            void moveToSuperclass() {
                if (skipSuperClasses) {
                    clazz = null;
                } else {
                    clazz = clazz.getSuperclass();
                    String clazzName = clazz.getName();
                    /** Skip system classes, this just degrades performance. */
                    if (clazzName.startsWith("java.") || clazzName.startsWith("javax.") || clazzName.startsWith("android.")) {
                        clazz = null;
                    }
                }
            }
        }
    
    • 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();
    
                // 忽略非 public 和 static 的方法
                if ((modifiers & Modifier.PUBLIC) != 0 && (modifiers & MODIFIERS_IGNORE) == 0) {
    
                    // 获取订阅方法的所有参数
                    Class<?>[] parameterTypes = method.getParameterTypes();
    
                    // 订阅方法只能有一个参数,否则忽略
                    if (parameterTypes.length == 1) {
                        // 获取有 Subscribe 的注解
                        Subscribe subscribeAnnotation = method.getAnnotation(Subscribe.class);
                        if (subscribeAnnotation != null) {
                            // 获取第一个参数
                            Class<?> eventType = parameterTypes[0];
    
                            // 检查 eventType 决定是否订阅,通常订阅者不能有多个 eventType 相同的订阅方法
                            if (findState.checkAdd(method, eventType)) {
                                // 获取线程模式
                                ThreadMode threadMode = subscribeAnnotation.threadMode();
    
                                // 添加订阅方法进 List
                                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");
                }
            }
        }
    
    • getMethodsAndRelease方法: 返回订阅者及其父类的订阅方法 List,并释放资源
    // 保存所有订阅方法
    final List<SubscriberMethod> subscriberMethods = new ArrayList<>();
    private static final int POOL_SIZE = 4;
    private static final FindState[] FIND_STATE_POOL = new FindState[POOL_SIZE];
    
    private List<SubscriberMethod> getMethodsAndRelease(FindState findState) {
            List<SubscriberMethod> 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;
        }
    

    上面这一堆方法都是讲的从反射获取订阅者的方法。 end

    下面这个方法表示从索引获取:

    • 通过 SubscriberIndex 方式获取
      findUsingInfo方法:
    private List<SubscriberMethod> findUsingInfo(Class<?> subscriberClass) {
            // 通过 prepareFindState 获取到 FindState(保存找到的注解过的方法的状态)
            FindState findState = prepareFindState();
    
            // findState 与 subscriberClass 关联
            findState.initForSubscriber(subscriberClass);
            while (findState.clazz != null) {
                // 获取订阅者信息
                // 通过 SubscriberIndex 获取 findState.clazz 对应的 SubscriberInfo
                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
                            findState.subscriberMethods.add(subscriberMethod);
                        }
                    }
                } else {
                    // 使用反射的方式获取单个类的订阅方法
                    findUsingReflectionInSingleClass(findState);
                }
                findState.moveToSuperclass();
            }
            return getMethodsAndRelease(findState);
        }
    

    这个方法里面的涉及到的方法在上面讲发射的时候都有了,这里就不重复了。引入一个新的接口:

    • SubscriberInfo:
    /**
     * Base class for generated index classes created by annotation processing.
     * 由批注处理创建的已生成索引类的基类
     */
    public interface SubscriberInfo {
        Class<?> getSubscriberClass();
    
        SubscriberMethod[] getSubscriberMethods();
    
        SubscriberInfo getSuperSubscriberInfo();
    
        boolean shouldCheckSuperclass();
    }
    
    • AbstractSubscriberInfo是SubscriberInfo 实现的抽象类
    /**
     * Base class for generated subscriber meta info classes created by annotation processing.
     * 由批注处理创建的已生成订阅服务器元信息类的基类
     */
    public abstract class AbstractSubscriberInfo implements SubscriberInfo {
        private final Class subscriberClass;
        private final Class<? extends SubscriberInfo> superSubscriberInfoClass;
        private final boolean shouldCheckSuperclass;
    
        protected AbstractSubscriberInfo(Class subscriberClass, Class<? extends SubscriberInfo> superSubscriberInfoClass,
                                         boolean shouldCheckSuperclass) {
            this.subscriberClass = subscriberClass;
            this.superSubscriberInfoClass = superSubscriberInfoClass;
            this.shouldCheckSuperclass = shouldCheckSuperclass;
        }
    
        @Override
        public Class getSubscriberClass() {
            return subscriberClass;
        }
    
        @Override
        public SubscriberInfo getSuperSubscriberInfo() {
            if (superSubscriberInfoClass == null) {
                return null;
            }
            try {
                return superSubscriberInfoClass.newInstance();
            } catch (InstantiationException e) {
                throw new RuntimeException(e);
            } catch (IllegalAccessException e) {
                throw new RuntimeException(e);
            }
        }
    
        @Override
        public boolean shouldCheckSuperclass() {
            return shouldCheckSuperclass;
        }
    
        protected SubscriberMethod createSubscriberMethod(String methodName, Class<?> eventType) {
            return createSubscriberMethod(methodName, eventType, ThreadMode.POSTING, 0, false);
        }
    
        protected SubscriberMethod createSubscriberMethod(String methodName, Class<?> eventType, ThreadMode threadMode) {
            return createSubscriberMethod(methodName, eventType, threadMode, 0, false);
        }
    
        protected SubscriberMethod createSubscriberMethod(String methodName, Class<?> eventType, ThreadMode threadMode,
                                                          int priority, boolean sticky) {
            try {
                Method method = subscriberClass.getDeclaredMethod(methodName, eventType);
                return new SubscriberMethod(method, eventType, threadMode, priority, sticky);
            } catch (NoSuchMethodException e) {
                throw new EventBusException("Could not find subscriber method in " + subscriberClass +
                        ". Maybe a missing ProGuard rule?", e);
            }
        }
    }
    
    • SimpleSubscriberInfo最终继承上面的抽象类
    /**
     * Uses {@link SubscriberMethodInfo} objects to create {@link SubscriberMethod} objects on demand.
     * 使用 SubscriberMethodInfo 对象根据需要创建 SubscriberMethod 对象。
     */
    public class SimpleSubscriberInfo extends AbstractSubscriberInfo {
    
        private final SubscriberMethodInfo[] methodInfos;
    
        public SimpleSubscriberInfo(Class subscriberClass, boolean shouldCheckSuperclass, SubscriberMethodInfo[] methodInfos) {
            super(subscriberClass, null, shouldCheckSuperclass);
            this.methodInfos = methodInfos;
        }
    
        @Override
        public synchronized SubscriberMethod[] getSubscriberMethods() {
            int length = methodInfos.length;
            SubscriberMethod[] methods = new SubscriberMethod[length];
            for (int i = 0; i < length; i++) {
                SubscriberMethodInfo info = methodInfos[i];
                methods[i] = createSubscriberMethod(info.methodName, info.eventType, info.threadMode,
                        info.priority, info.sticky);
            }
            return methods;
        }
    }
    
    • 最后就是要创建出的 SubscriberMethod 对象
    /**
     * Used internally by EventBus and generated subscriber indexes.
     *
     * 封装了EventBus中的参数,就是一个EventBus订阅方法包装类
     */
    public class SubscriberMethod {
        final Method method;
        final ThreadMode threadMode;
        final Class<?> eventType;
        final int priority;
        final boolean sticky;
    
        /**
         * Used for efficient comparison
         */
        String methodString;
    
        public SubscriberMethod(Method method, Class<?> eventType, ThreadMode threadMode, int priority, boolean sticky) {
            this.method = method;
            this.threadMode = threadMode;
            this.eventType = eventType;
            this.priority = priority;
            this.sticky = sticky;
        }
    
        @Override
        public boolean equals(Object other) {
            if (other == this) {
                return true;
            } else if (other instanceof SubscriberMethod) {
                checkMethodString();
                SubscriberMethod otherSubscriberMethod = (SubscriberMethod) other;
                otherSubscriberMethod.checkMethodString();
                // Don't use method.equals because of http://code.google.com/p/android/issues/detail?id=7811#c6
                return methodString.equals(otherSubscriberMethod.methodString);
            } else {
                return false;
            }
        }
    
        private synchronized void checkMethodString() {
            if (methodString == null) {
                // Method.toString has more overhead, just take relevant parts of the method
                StringBuilder builder = new StringBuilder(64);
                builder.append(method.getDeclaringClass().getName());
                builder.append('#').append(method.getName());
                builder.append('(').append(eventType.getName());
                methodString = builder.toString();
            }
        }
    
        @Override
        public int hashCode() {
            return method.hashCode();
        }
    }
    

    到这里索引也分析完了,索引的具体使用:https://www.jianshu.com/p/1e624bf9144d

    接下来注册的关键性一步:将订阅者和订阅者放方法形成订阅关系
    subscribe方法:

    // Must be called in synchronized block  必须组同步块中调用
        private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) {
            Class<?> eventType = subscriberMethod.eventType;
    
            // 创建 Subscription 封装订阅者和订阅方法信息
            Subscription newSubscription = new Subscription(subscriber, subscriberMethod);
    
            // 可并发读写的 ArrayList(CopyOnWriteArrayList)),key为 EventType,value为 Subscriptions
            // 根据事件类型从 subscriptionsByEventType 这个 Map 中获取 Subscription 集合
            CopyOnWriteArrayList<Subscription> subscriptions = subscriptionsByEventType.get(eventType);
    
            // 如果为 null,表示还没有(注册)订阅过,创建并 put 进 Map
            if (subscriptions == null) {
                subscriptions = new CopyOnWriteArrayList<>();
                subscriptionsByEventType.put(eventType, subscriptions);
            } else {
                // 若subscriptions中已经包含newSubscription,表示该newSubscription已经被订阅过,抛出异常
                if (subscriptions.contains(newSubscription)) {
                    throw new EventBusException("Subscriber " + subscriber.getClass() + " already registered to event "
                            + eventType);
                }
            }
    
            // 按照优先级插入subscriptions
            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;
                }
            }
    
            // key为订阅者,value为eventType,用来存放订阅者中的事件类型
            List<Class<?>> subscribedEvents = typesBySubscriber.get(subscriber);
            if (subscribedEvents == null) {
                subscribedEvents = new ArrayList<>();
                typesBySubscriber.put(subscriber, subscribedEvents);
            }
    
            // 将EventType放入subscribedEvents的集合中
            subscribedEvents.add(eventType);
    
            //判断是否为Sticky事件
            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>).
                    // 获取到所有Sticky事件的Set集合
                    Set<Map.Entry<Class<?>, Object>> entries = stickyEvents.entrySet();
    
                    //遍历所有Sticky事件
                    for (Map.Entry<Class<?>, Object> entry : entries) {
                        Class<?> candidateEventType = entry.getKey();
    
                        //判断当前事件类型是否为黏性事件或者其子类
                        if (eventType.isAssignableFrom(candidateEventType)) {
                            Object stickyEvent = entry.getValue();
    
                            // 执行设置了 sticky 模式的订阅方法
                            checkPostStickyEventToSubscription(newSubscription, stickyEvent);
                        }
                    }
                } else {
                    Object stickyEvent = stickyEvents.get(eventType);
                    checkPostStickyEventToSubscription(newSubscription, stickyEvent);
                }
            }
        }
    
    • 这里涉及到一个类Subscription:
    // 封装订阅者和订阅方法信息
    final class Subscription {
        final Object subscriber; // 订阅者对象
        final SubscriberMethod subscriberMethod; // 订阅的方法
    }
    
    • 检查有没有post粘性的事件
    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方法: 这里调用主要是为了检查没有注册之前是否发送了黏性事件
    /**
         * 订阅者五种线程模式的特点对应的就是以上代码,简单来讲就是订阅者指定了在哪个线程订阅事件,无论发布者在哪个线程,它都会将事件发布到订阅者指定的线程
         * @param subscription
         * @param event
         * @param isMainThread
         */
        private void postToSubscription(Subscription subscription, Object event, boolean isMainThread) {
            switch (subscription.subscriberMethod.threadMode) {
    
                // 订阅线程跟随发布线程,EventBus 默认的订阅方式
                case POSTING:
                    invokeSubscriber(subscription, event);  // 订阅线程和发布线程相同,直接订阅
                    break;
    
                // 订阅线程为主线程
                case MAIN:
                    if (isMainThread) { // 如果 post是在 UI 线程,直接调用 invokeSubscriber
                        invokeSubscriber(subscription, event);
                    } else {
    
                        // 如果不在 UI 线程,用 mainThreadPoster 进行调度,即上文讲述的 HandlerPoster 的 Handler 异步处理,将订阅线程切换到主线程订阅
                        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:
    
                    // 如果在 UI 线程,则将 subscription 添加到后台线程的线程池
                    if (isMainThread) {
                        backgroundPoster.enqueue(subscription, event);
                    } else {
                        // 不在UI线程,直接分发
                        invokeSubscriber(subscription, event);
                    }
                    break;
    
                // 订阅线程为异步线程
                case ASYNC:
                    // 使用线程池线程订阅
                    asyncPoster.enqueue(subscription, event);
                    break;
                default:
                    throw new IllegalStateException("Unknown thread mode: " + subscription.subscriberMethod.threadMode);
            }
        }
    

    到这里注册流程就分析完了,下面贴上一张整体流程图:


    注册流程图

    3.书写接收订阅事件的方法

    @Subscribe(threadMode = ThreadMode.POSTING,sticky = false,priority = 4)
        public void onEventThread(EventCenter eventCenter){
            switch (eventCenter.getEventType()) {
            case EventType.ONE:
                Log.e("MainActivity", eventCenter.getEventType());
                break;
    
            default:
                break;
            }
            // EventBus.getDefault().cancelEventDelivery(eventCenter);
        }
    
    • 这里主要涉及到注解及黏性事件。
      注解:
    @Documented  // 命名为 java doc 文档
    @Retention(RetentionPolicy.RUNTIME) // 指定在运行时有效,即在运行时能保持这个 Subscribe
    @Target({ElementType.METHOD})  // 指定类型为 METHOD,表名用来描述方法
    public @interface Subscribe {
    
        // 指定线程模式,可以指定在 Subscribe 中接收的 Event 所处的线程
        ThreadMode threadMode() default ThreadMode.POSTING;  // 订阅线程的模式,默认从哪个线程发送,就从哪个线程订阅
    
        /**
         * If true, delivers the most recent sticky event (posted with
         * {@link EventBus#postSticky(Object)}) to this subscriber (if event available).
         * 粘性事件是事件消费者在事件发布之后才注册,依然能接收到该事件的特殊类型。
         */
        boolean sticky() default false;
    
        /** 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! 
         * 数值越高优先级越大,越先接收事件
         * */
        int priority() default 0;
    }
    

    总结:

    • 粘性事件是事件消费者在事件发布之后才注册,依然能接收到该事件的特殊类型
    • 任何时候在任何一个订阅了该事件的订阅者中的任何地方,都可以通 EventBus.getDefault().getStickyEvent(MyEvent.class)来取得该类型事件的最后一次缓存。
    • 优先级priority数值越高优先级越大,越先接收事件

    线程模式ThreadMode

    /**
     * Each subscriber method has a thread mode, which determines in which thread the method is to be called by EventBus.
     * EventBus takes care of threading independently from the posting thread.
     *
     * 每个订阅服务器方法都有一个线程模式,该模式决定EventBus在哪个线程中调用该方法。EventBus独立于发布线程来处理线程。
     * 
     * @see EventBus#register(Object)
     * @author Markus
     */
    public enum ThreadMode {
        /**
         * Subscriber will be called directly in the same thread, which is posting the event. This is the default. Event delivery
         * implies the least overhead because it avoids thread switching completely. Thus this is the recommended mode for
         * simple tasks that are known to complete in a very short time without requiring the main thread. Event handlers
         * using this mode must return quickly to avoid blocking the posting thread, which may be the main thread.
         *
         * 订阅服务器将直接在发布事件的同一线程中调用。这是默认设置。事件传递意味着开销最小,因为它完全避免了线程切换。
         * 因此,对于已知在非常短的时间内完成而不需要主线程的简单任务,建议使用这种模式。
         * 使用此模式的事件处理程序必须快速返回,以避免阻塞可能是主线程的发布线程。
         */
        POSTING,  // EventBus 默认的线程模式 就是订阅的线程和发送事件的线程为同一线程
    
        /**
         * On Android, subscriber will be called in Android's main thread (UI thread). If the posting thread is
         * the main thread, subscriber methods will be called directly, blocking the posting thread. Otherwise the event
         * is queued for delivery (non-blocking). Subscribers using this mode must return quickly to avoid blocking the main thread.
         * If not on Android, behaves the same as {@link #POSTING}.
         *
         *
         * 在Android上,用户将在Android的主线程(UI线程)中被调用。
         * 如果发布线程是主线程,则将直接调用订阅方法,从而阻塞发布线程。否则,事件将排队等待传递(非阻塞)。
         * 使用此模式的订阅必须快速返回,以避免阻塞主线程。如果不在Android上,其行为与 POSTING 发布相同。
         * 因为安卓主线程阻塞会发生 ANR 异常
         */
        MAIN,  // 主线程
    
        /**
         * On Android, subscriber will be called in Android's main thread (UI thread). Different from {@link #MAIN},
         * the event will always be queued for delivery. This ensures that the post call is non-blocking.
         *
         * 在Android上,用户将在Android的主线程(UI线程)中被调用。与 MAIN 不同,事件将始终排队等待传递。这样可以确保后调用不阻塞
         */
        MAIN_ORDERED, // 主线程
    
        /**
         * On Android, subscriber will be called in a background thread. If posting thread is not the main thread, subscriber methods
         * will be called directly in the posting thread. If the posting thread is the main thread, EventBus uses a single
         * background thread, that will deliver all its events sequentially. Subscribers using this mode should try to
         * return quickly to avoid blocking the background thread. If not on Android, always uses a background thread.
         *
         * 在Android上,订阅将在后台线程中被调用。如果发布线程不是主线程,则将直接在发布线程中调用订阅方法。
         * 如果发布线程是主线程,那么 eventBus 使用单个后台线程,该线程将按顺序传递其所有事件。
         * 使用此模式的订阅应尝试快速返回,以避免阻塞后台线程。如果不在Android上,则始终使用后台线程。
         *
         */
        BACKGROUND,  // 后台线程
    
        /**
         * Subscriber will be called in a separate thread. This is always independent from the posting thread and the
         * main thread. Posting events never wait for subscriber methods using this mode. Subscriber methods should
         * use this mode if their execution might take some time, e.g. for network access. Avoid triggering a large number
         * of long running asynchronous subscriber methods at the same time to limit the number of concurrent threads. EventBus
         * uses a thread pool to efficiently reuse threads from completed asynchronous subscriber notifications.
         *
         * 将在单独的线程中调用订阅服务器。这始终独立于发布线程和主线程。
         * 发布事件从不等待使用此模式的订阅方法。
         * 如果订阅服务器方法的执行可能需要一些时间,例如用于网络访问,则应使用此模式。
         * 避免同时触发大量长时间运行的异步订阅服务器方法,以限制并发线程的数量。
         * EventBus使用线程池来有效地重用已完成的异步订阅服务器通知中的线程。
         *
         */
        ASYNC // 异步线程
    }
    

    4.发送事件给订阅者

    // 发送黏性事件
    EventBus.getDefault().postSticky(new EventCenter<>(EventType.ONE));
    // 发送普通事件
    EventBus.getDefault().post(new EventCenter<>(EventType.ONE));
    
    • postSticky方法:
    public void postSticky(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);
        }
    
    • post方法:
    /**
         * Posts the given event to the event bus.
         * 将给定事件发布到事件总线
         */
        public void post(Object event) {
    
            // 获取当前线程的 posting 状态
            PostingThreadState postingState = currentPostingThreadState.get();
    
            // 获取当前事件队列
            List<Object> eventQueue = postingState.eventQueue;
    
            // 将事件添加进当前线程的事件队列
            eventQueue.add(event);
    
            // 判断是否正在posting(发送))
            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;
                }
            }
        }
    
    • 发送事件的线程封装类 PostingThreadState
    /**
         * For ThreadLocal, much faster to set (and get multiple values).
         *
         * 发送事件的线程封装类
         */
        final static class PostingThreadState {
            final List<Object> eventQueue = new ArrayList<>();  // 事件队列
            boolean isPosting; // 是否正在 posting
            boolean isMainThread;  // 是否为主线程
            Subscription subscription;
            Object event;
            boolean canceled; // 是否已经取消
        }
    
    • postSingleEvent 发送方法:
    /**
         * 发送事件
         *
         * EventBus 用 ThreadLocal 存储每个线程的 PostingThreadState,一个存储了事件发布状态的类,
         * 当 post 一个事件时,添加到事件队列末尾,等待前面的事件发布完毕后再拿出来发布,
         * 这里看事件发布的关键代码postSingleEvent()
         */
        private void postSingleEvent(Object event, PostingThreadState postingState) throws Error {
            Class<?> eventClass = event.getClass();
            boolean subscriptionFound = false;
            if (eventInheritance) { // 处理继承事件
                List<Class<?>> 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)); // 如果没有人和订阅者订阅发送 NoSubscriberEvent
                }
            }
        }
    
    • lookupAllEventTypes方法:
    /**
         * Looks up all Class objects including super classes and interfaces. Should also work for interfaces.
         * 看看涉及到lookupAllEventTypes,就是查找到发生事件的所有相关类(父类)
         */
        private static List<Class<?>> lookupAllEventTypes(Class<?> eventClass) {
            synchronized (eventTypesCache) {
                List<Class<?>> 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;
            }
        }
    
    /**
         * Recurses through super interfaces. 遍历父类接口
         */
        static void addInterfaces(List<Class<?>> eventTypes, Class<?>[] interfaces) {
            for (Class<?> interfaceClass : interfaces) {
                if (!eventTypes.contains(interfaceClass)) {
                    eventTypes.add(interfaceClass);
                    addInterfaces(eventTypes, interfaceClass.getInterfaces()); // 递归
                }
            }
        }
    
    • postSingleEventForEventType方法:
    // 进一步深入的发送事件函数:
        private boolean postSingleEventForEventType(Object event, PostingThreadState postingState, Class<?> eventClass) {
            CopyOnWriteArrayList<Subscription> subscriptions;
            synchronized (this) {
                subscriptions = subscriptionsByEventType.get(eventClass); // 查找是否存在处理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;
        }
    

    最终走了这个方法postToSubscription()进行事件发送

    /**
         * 订阅者五种线程模式的特点对应的就是以上代码,简单来讲就是订阅者指定了在哪个线程订阅事件,无论发布者在哪个线程,它都会将事件发布到订阅者指定的线程
         * @param subscription
         * @param event
         * @param isMainThread
         */
        private void postToSubscription(Subscription subscription, Object event, boolean isMainThread) {
            switch (subscription.subscriberMethod.threadMode) {
    
                // 订阅线程跟随发布线程,EventBus 默认的订阅方式
                case POSTING:
                    invokeSubscriber(subscription, event);  // 订阅线程和发布线程相同,直接订阅
                    break;
    
                // 订阅线程为主线程
                case MAIN:
                    if (isMainThread) { // 如果 post是在 UI 线程,直接调用 invokeSubscriber
                        invokeSubscriber(subscription, event);
                    } else {
    
                        // 如果不在 UI 线程,用 mainThreadPoster 进行调度,即上文讲述的 HandlerPoster 的 Handler 异步处理,将订阅线程切换到主线程订阅
                        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:
    
                    // 如果在 UI 线程,则将 subscription 添加到后台线程的线程池
                    if (isMainThread) {
                        backgroundPoster.enqueue(subscription, event);
                    } else {
                        // 不在UI线程,直接分发
                        invokeSubscriber(subscription, event);
                    }
                    break;
    
                // 订阅线程为异步线程
                case ASYNC:
                    // 使用线程池线程订阅
                    asyncPoster.enqueue(subscription, event);
                    break;
                default:
                    throw new IllegalStateException("Unknown thread mode: " + subscription.subscriberMethod.threadMode);
            }
        }
    

    到这里事件发送也分析完了,老规矩附上流程图:

    post事件流程图

    由于篇幅所限,剩下的内容传送门:https://www.jianshu.com/p/f61b8e7da6b4

    相关文章

      网友评论

        本文标题:EventBus源码解读

        本文链接:https://www.haomeiwen.com/subject/nyygeqtx.html