EventBus源码解读

上一篇中我们讲解了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, List>> eventTypesCache = new HashMap<>();

    // key 为事件类型,value为封装订阅者和订阅方法的对象的集合
    private final Map, CopyOnWriteArrayList> subscriptionsByEventType;

    // key为订阅者,value为eventType的List集合,用来存放订阅者中的事件类型
    private final Map>> typesBySubscriber;

    //key为 eventType(事件类型对象的字节码),value为发送的事件对象
    private final Map, Object> stickyEvents; // 黏性事件

    // currentPostingThreadState
    private final ThreadLocal currentPostingThreadState = new ThreadLocal() {
        @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> skipMethodVerificationForClasses;   // 需要跳过执行方法验证的类
    List 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%
     * 

* 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. 为所有事件总线日志记录设置特定的日志处理程序。 *

* 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 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, List> METHOD_CACHE = new ConcurrentHashMap<>();

/**
     * 订阅方法查找
     * @param subscriberClass 订阅者对象
     * @return 返回订阅者 所有的订阅方法 是一个List集合
     */
    List findSubscriberMethods(Class subscriberClass) {
        // 首先在 METHOD_CACHE 中查找该 Event 对应的订阅者集合是否已经存在,如果有直接返回
        List 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 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 subscriberMethods = new ArrayList<>();

        // 事件类型为Key,订阅方法为Value
        final Map anyMethodByEventType = new HashMap<>();

        // 订阅方法为Key,订阅者的Class对象为Value
        final Map 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 subscriberMethods = new ArrayList<>();
private static final int POOL_SIZE = 4;
private static final FindState[] FIND_STATE_POOL = new FindState[POOL_SIZE];

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;
    }

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

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

  • 通过 SubscriberIndex 方式获取
    findUsingInfo方法:
private List 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 superSubscriberInfoClass;
    private final boolean shouldCheckSuperclass;

    protected AbstractSubscriberInfo(Class subscriberClass, Class 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 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> 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).
                // 获取到所有Sticky事件的Set集合
                Set, Object>> entries = stickyEvents.entrySet();

                //遍历所有Sticky事件
                for (Map.Entry, 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 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 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> 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> 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;
        }
    }

/**
     * Recurses through super interfaces. 遍历父类接口
     */
    static void addInterfaces(List> 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 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源码解读)