欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

EventBus三之手写EventBus

程序员文章站 2024-02-28 13:29:52
...

目录

  • 项目模块描述
  • eventbus_annotation模块
  • eventbus_compiler模块
  • eventbus模块
  • 代码传送门

项目模块描述

EventBus三之手写EventBus

eventbus类图

EventBus三之手写EventBus

eventbus时序图

EventBus三之手写EventBus

eventbus_annotation 实现

a)定义注解类Subscribe

@Target(ElementType.METHOD) // 该注解作用在方法之上
@Retention(RetentionPolicy.CLASS) // 要在编译时进行一些预处理操作,注解会在class文件中存在
public @interface Subscribe {

    // 线程模式,默认推荐POSTING(订阅、发布在同一线程)
    ThreadMode threadMode() default ThreadMode.POSTING;

    // 是否使用粘性事件
    boolean sticky() default false;

    // 事件订阅优先级,在同一个线程中。数值越大优先级越高。
    int priority() default 0;
}

b)定义ThreadMode

public enum ThreadMode {
    // 订阅、发布在同一线程。避免了线程切换,也是推荐的默认模式
    POSTING,
    // 主线程(UI线程)中被调用,切勿耗时操作
    MAIN,
    // 用于网络访问等耗时操作,事件总线已完成的异步订阅通知线程。并使用线程池有效地重用
    ASYNC
}

c)定义订阅方法的描述类

public interface SubscriberInfo {
    // 订阅所属类,比如:MainActivity
    Class<?> getSubscriberClass();
    // 获取订阅所属类中所有订阅事件的方法(此处不使用List是因为注解处理器每次都要list.clear(),麻烦!)
    SubscriberMethod[] getSubscriberMethods();
}

public class EventBeans implements SubscriberInfo {
    // 订阅者对象Class,如:MainActivity.class
    private final Class subscriberClass;
    // 订阅方法数组,参考SimpleSubscriberInfo.java 25行
    private final SubscriberMethod[] methodInfos;
    public EventBeans(Class subscriberClass, SubscriberMethod[] methodInfos) {
        this.subscriberClass = subscriberClass;
        this.methodInfos = methodInfos;
    }
    @Override
    public Class<?> getSubscriberClass() {
        return subscriberClass;
    }

    @Override
    public synchronized SubscriberMethod[] getSubscriberMethods() {
        return methodInfos;
    }
}

public class SubscriberMethod {

    private String methodName; // 订阅方法名
    private Method method; // 订阅方法,用于最后的自动执行订阅方法
    private ThreadMode threadMode; // 线程模式
    private Class<?> eventType; // 事件对象Class,如:UserInfo.class
    private int priority; // 事件订阅优先级(实现思路:重排序集合中方法的顺序)
    private boolean sticky; // 是否粘性事件(实现思路:发送时存储,注册时判断粘性再**)

    public SubscriberMethod(Class subscriberClass, String methodName,
                            Class<?> eventType, ThreadMode threadMode, int priority, boolean sticky) {
        this.methodName = methodName;
        this.threadMode = threadMode;
        this.eventType = eventType;
        this.priority = priority;
        this.sticky = sticky;
        try {
            // 订阅所属类(参考源码:AbstractSubscriberInfo.java - 72行)
            method = subscriberClass.getDeclaredMethod(methodName, eventType);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }
    }
	...
}

d)定义订阅索引接口

public interface SubscriberInfoIndex {
    /**
     * 生成索引接口,通过订阅者对象(MainActivity.class)获取所有订阅方法
     *
     * @param subscriberClass 订阅者对象Class,如:MainActivity.class
     * @return 事件订阅方法封装类
     */
    SubscriberInfo getSubscriberInfo(Class<?> subscriberClass);
}

eventbus_compiler 实现

// 注解处理器的实现

/**
 * 编码此类1句话:细心再细心,出了问题debug真的不好调试
 */
// 用来生成 META-INF/services/javax.annotation.processing.Processor 文件
@AutoService(Processor.class)
// 允许/支持的注解类型,让注解处理器处理
@SupportedAnnotationTypes({Constants.SUBSCRIBE_ANNOTATION_TYPES})
// 指定JDK编译版本
@SupportedSourceVersion(SourceVersion.RELEASE_7)
// 注解处理器接收的参数
@SupportedOptions({Constants.PACKAGE_NAME, Constants.CLASS_NAME})
public class SubscribeProcessor extends AbstractProcessor {

    // 操作Element工具类 (类、函数、属性都是Element)
    private Elements elementUtils;

    // type(类信息)工具类,包含用于操作TypeMirror的工具方法
    private Types typeUtils;

    // Messager用来报告错误,警告和其他提示信息
    private Messager messager;

    // 文件生成器 类/资源,Filter用来创建新的类文件,class文件以及辅助文件
    private Filer filer;

    // APT包名
    private String packageName;

    // APT类名
    private String className;

    // 临时map存储,用来存放订阅方法信息,生成路由组类文件时遍历
    // key:组名"MainActivity", value:MainActivity中订阅方法集合
    private final Map<TypeElement, List<ExecutableElement>> methodsByClass = new HashMap<>();

    // 该方法主要用于一些初始化的操作,通过该方法的参数ProcessingEnvironment可以获取一些列有用的工具类
    @Override
    public synchronized void init(ProcessingEnvironment processingEnvironment) {
        super.init(processingEnvironment);
        // 初始化
        elementUtils = processingEnvironment.getElementUtils();
        typeUtils = processingEnvironment.getTypeUtils();
        messager = processingEnvironment.getMessager();
        filer = processingEnvironment.getFiler();

        // 通过ProcessingEnvironment去获取对应的参数
        Map<String, String> options = processingEnvironment.getOptions();
        if (!EmptyUtils.isEmpty(options)) {
            packageName = options.get(Constants.PACKAGE_NAME);
            className = options.get(Constants.CLASS_NAME);
            messager.printMessage(Diagnostic.Kind.NOTE,
                    "packageName >>> " + packageName + " / className >>> " + className);
        }

        // 必传参数判空(乱码问题:添加java控制台输出中文乱码)
        if (EmptyUtils.isEmpty(packageName) || EmptyUtils.isEmpty(className)) {
            messager.printMessage(Diagnostic.Kind.ERROR, "注解处理器需要的参数为空,请在对应build.gradle配置参数");
        }
    }

    /**
     * 相当于main函数,开始处理注解
     * 注解处理器的核心方法,处理具体的注解,生成Java文件
     *
     * @param set              使用了支持处理注解的节点集合
     * @param roundEnvironment 当前或是之前的运行环境,可以通过该对象查找的注解。
     * @return true 表示后续处理器不会再处理(已经处理完成)
     */
    @Override
    public boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment) {
        // 一旦有类之上使用@Subscribe注解
        if (!EmptyUtils.isEmpty(set)) {
            // 获取所有被 @Subscribe 注解的 元素集合
            Set<? extends Element> elements = roundEnvironment.getElementsAnnotatedWith(Subscribe.class);

            if (!EmptyUtils.isEmpty(elements)) {
                // 解析元素
                try {
                    parseElements(elements);
                    return true;
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return true;
        }
        return false;
    }

    // 解析所有被 @Subscribe 注解的 类元素集合
    private void parseElements(Set<? extends Element> elements) throws IOException {

        // 遍历节点
        for (Element element : elements) {
            // @Subscribe注解只能在方法之上(尽量避免使用instanceof进行判断)
            if (element.getKind() != ElementKind.METHOD) {
                messager.printMessage(Diagnostic.Kind.ERROR, "仅解析@Subscribe注解在方法上元素");
                return;
            }
            // 强转方法元素
            ExecutableElement method = (ExecutableElement) element;
            // 检查方法,条件:订阅方法必须是非静态的,公开的,参数只能有一个
            if (checkHasNoErrors(method)) {
                // 获取封装订阅方法的类(方法上一个节点)
                TypeElement classElement = (TypeElement) method.getEnclosingElement();

                // 以类名为key,保存订阅方法
                List<ExecutableElement> methods = methodsByClass.get(classElement);
                if (methods == null) {
                    methods = new ArrayList<>();
                    methodsByClass.put(classElement, methods);
                }
                methods.add(method);
            }

            messager.printMessage(Diagnostic.Kind.NOTE, "遍历注解方法:" + method.getSimpleName().toString());
        }

        // 通过Element工具类,获取SubscriberInfoIndex类型
        TypeElement subscriberIndexType = elementUtils.getTypeElement(Constants.SUBSCRIBERINFO_INDEX);

        // 生成类文件
        createFile(subscriberIndexType);
    }

    private void createFile(TypeElement subscriberIndexType) throws IOException {
        // 添加静态块代码:SUBSCRIBER_INDEX = new HashMap<Class, SubscriberInfo>();
        CodeBlock.Builder codeBlock = CodeBlock.builder();
        codeBlock.addStatement("$N = new $T<$T, $T>()",
                Constants.FIELD_NAME,
                HashMap.class,
                Class.class,
                SubscriberInfo.class);

        // 双层循环,第一层遍历被@Subscribe注解的方法所属类。第二层遍历每个类中所有订阅的方法
        for (Map.Entry<TypeElement, List<ExecutableElement>> entry : methodsByClass.entrySet()) {
            // 此处不能使用codeBlock,会造成错误嵌套
            CodeBlock.Builder contentBlock = CodeBlock.builder();
            CodeBlock contentCode = null;
            String format;
            for (int i = 0; i < entry.getValue().size(); i++) {
                // 获取每个方法上的@Subscribe注解中的注解值
                Subscribe subscribe = entry.getValue().get(i).getAnnotation(Subscribe.class);
                // 获取订阅事件方法所有参数
                List<? extends VariableElement> parameters = entry.getValue().get(i).getParameters();
                // 获取订阅事件方法名
                String methodName = entry.getValue().get(i).getSimpleName().toString();
                // 注意:此处还可以做检查工作,比如:参数类型必须是类或接口类型(这里缩减了)
                TypeElement parameterElement = (TypeElement) typeUtils.asElement(parameters.get(0).asType());
                // 如果是最后一个添加,则无需逗号结尾
                if (i == entry.getValue().size() - 1) {
                    format = "new $T($T.class, $S, $T.class, $T.$L, $L, $L)";
                } else {
                    format = "new $T($T.class, $S, $T.class, $T.$L, $L, $L),\n";
                }
                // new SubscriberMethod(MainActivity.class, "abc", UserInfo.class, ThreadMode.POSTING, 0, false)
                contentCode = contentBlock.add(format,
                        SubscriberMethod.class,
                        ClassName.get(entry.getKey()),
                        methodName,
                        ClassName.get(parameterElement),
                        ThreadMode.class,
                        subscribe.threadMode(),
                        subscribe.priority(),
                        subscribe.sticky())
                        .build();
            }

            if (contentCode != null) {
                // putIndex(new EventBeans(MainActivity.class, new SubscriberMethod[] {)
                codeBlock.beginControlFlow("putIndex(new $T($T.class, new $T[]",
                        EventBeans.class,
                        ClassName.get(entry.getKey()),
                        SubscriberMethod.class)
                        // 嵌套的精华(尝试了很多次,有更好的方式请告诉我)
                        .add(contentCode)
                        // ))}
                        .endControlFlow("))");
            } else {
                messager.printMessage(Diagnostic.Kind.ERROR, "注解处理器双层循环发生错误!");
            }
        }

        // 全局属性:Map<Class<?>, SubscriberMethod>
        TypeName fieldType = ParameterizedTypeName.get(
                ClassName.get(Map.class), // Map
                ClassName.get(Class.class), // Map<Class,
                ClassName.get(SubscriberInfo.class) // Map<Class, SubscriberMethod>
        );

        // putIndex方法参数:putIndex(SubscriberInfo info)
        ParameterSpec putIndexParameter = ParameterSpec.builder(
                ClassName.get(SubscriberInfo.class),
                Constants.PUTINDEX_PARAMETER_NAME)
                .build();

        // putIndex方法配置:private static void putIndex(SubscriberMethod info) {
        MethodSpec.Builder putIndexBuidler = MethodSpec
                .methodBuilder(Constants.PUTINDEX_METHOD_NAME) // 方法名
                .addModifiers(Modifier.PRIVATE, Modifier.STATIC) // private static修饰符
                .addParameter(putIndexParameter); // 添加方法参数
        // 不填returns默认void返回值

        // putIndex方法内容:SUBSCRIBER_INDEX.put(info.getSubscriberClass(), info);
        putIndexBuidler.addStatement("$N.put($N.getSubscriberClass(), $N)",
                Constants.FIELD_NAME,
                Constants.PUTINDEX_PARAMETER_NAME,
                Constants.PUTINDEX_PARAMETER_NAME);

        // getSubscriberInfo方法参数:Class subscriberClass
        ParameterSpec getSubscriberInfoParameter = ParameterSpec.builder(
                ClassName.get(Class.class),
                Constants.GETSUBSCRIBERINFO_PARAMETER_NAME)
                .build();

        // getSubscriberInfo方法配置:public SubscriberMethod getSubscriberInfo(Class<?> subscriberClass) {
        MethodSpec.Builder getSubscriberInfoBuidler = MethodSpec
                .methodBuilder(Constants.GETSUBSCRIBERINFO_METHOD_NAME) // 方法名
                .addAnnotation(Override.class) // 重写方法注解
                .addModifiers(Modifier.PUBLIC) // public修饰符
                .addParameter(getSubscriberInfoParameter) // 方法参数
                .returns(SubscriberInfo.class); // 方法返回值

        // getSubscriberInfo方法内容:return SUBSCRIBER_INDEX.get(subscriberClass);
        getSubscriberInfoBuidler.addStatement("return $N.get($N)",
                Constants.FIELD_NAME,
                Constants.GETSUBSCRIBERINFO_PARAMETER_NAME);

        // 构建类
        TypeSpec typeSpec = TypeSpec.classBuilder(className)
                // 实现SubscriberInfoIndex接口
                .addSuperinterface(ClassName.get(subscriberIndexType))
                // 该类的修饰符
                .addModifiers(Modifier.PUBLIC, Modifier.FINAL)
                // 添加静态块(很少用的api)
                .addStaticBlock(codeBlock.build())
                // 全局属性:private static final Map<Class<?>, SubscriberMethod> SUBSCRIBER_INDEX
                .addField(fieldType, Constants.FIELD_NAME, Modifier.PRIVATE, Modifier.STATIC, Modifier.FINAL)
                // 第一个方法:加入全局Map集合
                .addMethod(putIndexBuidler.build())
                // 第二个方法:通过订阅者对象(MainActivity.class)获取所有订阅方法
                .addMethod(getSubscriberInfoBuidler.build())
                .build();

        // 生成类文件:EventBusIndex
        JavaFile.builder(packageName, // 包名
                typeSpec) // 类构建完成
                .build() // JavaFile构建完成
                .writeTo(filer); // 文件生成器开始生成类文件
    }

    /**
     * 检查方法,条件:订阅方法必须是非静态的,公开的,参数只能有一个
     *
     * @param element 方法元素
     * @return 检查是否通过
     */
    private boolean checkHasNoErrors(ExecutableElement element) {
        // 不能为static静态方法
        if (element.getModifiers().contains(Modifier.STATIC)) {
            messager.printMessage(Diagnostic.Kind.ERROR, "订阅事件方法不能是static静态方法", element);
            return false;
        }

        // 必须是public修饰的方法
        if (!element.getModifiers().contains(Modifier.PUBLIC)) {
            messager.printMessage(Diagnostic.Kind.ERROR, "订阅事件方法必须是public修饰的方法", element);
            return false;
        }

        // 订阅事件方法必须只有一个参数
        List<? extends VariableElement> parameters = ((ExecutableElement) element).getParameters();
        if (parameters.size() != 1) {
            messager.printMessage(Diagnostic.Kind.ERROR, "订阅事件方法有且仅有一个参数", element);
            return false;
        }
        return true;
    }

}

EventBus的实现

public class EventBus {

    // volatile修饰的变量不允许线程内部缓存和重排序,即直接修改内存
    private static volatile EventBus defaultInstance;
    // 索引接口
    private SubscriberInfoIndex subscriberInfoIndexes;
    // 订阅者类型集合,比如:订阅者MainActivity订阅了哪些EventBean,或者解除订阅的缓存。
    // key:订阅者MainActivity.class,value:EventBean集合
    private Map<Object, List<Class<?>>> typesBySubscriber;
    // 方法缓存:key:订阅者MainActivity.class,value:订阅方法集合
    private static final Map<Class<?>, List<SubscriberMethod>> METHOD_CACHE = new ConcurrentHashMap<>();
    // EventBean缓存,key:UserInfo.class,value:订阅者(可以是多个Activity)中所有订阅的方法集合
    private Map<Class<?>, CopyOnWriteArrayList<Subscription>> subscriptionsByEventType;
    // 粘性事件缓存,key:UserInfo.class,value:UserInfo
    private final Map<Class<?>, Object> stickyEvents;
    // 发送(子线程) - 订阅(主线程)
    private Handler handler;
    // 发送(主线程) - 订阅(子线程)
    private ExecutorService executorService;

    private EventBus() {
        // 初始化缓存集合
        typesBySubscriber = new HashMap<>();
        subscriptionsByEventType = new HashMap<>();
        stickyEvents = new HashMap<>();
        // Handler高级用法:将handler放在主线程使用
        handler = new Handler(Looper.getMainLooper());
        // 创建一个子线程(缓存线程池)
        executorService = Executors.newCachedThreadPool();
    }

    // 单例,全局唯一,参考EventBus.java 80行
    public static EventBus getDefault() {
        if (defaultInstance == null) {
            synchronized (EventBus.class) {
                if (defaultInstance == null) {
                    defaultInstance = new EventBus();
                }
            }
        }
        return defaultInstance;
    }

    // 添加索引(简化),接口 = 接口实现类,参考EventBusBuilder.java 136行
    public void addIndex(SubscriberInfoIndex index) {
        subscriberInfoIndexes = index;
    }

    // 注册 / 订阅事件,参考EventBus.java 138行
    public void register(Object subscriber) {
        // 获取MainActivity.class
        Class<?> subscriberClass = subscriber.getClass();
        // 寻找(MainActivity.class)订阅方法集合
        List<SubscriberMethod> subscriberMethods = findSubscriberMethods(subscriberClass);
        synchronized (this) { // 同步锁,并发少可考虑删除(参考源码)
            for (SubscriberMethod subscriberMethod : subscriberMethods) {
                // 遍历后,开始订阅
                subscribe(subscriber, subscriberMethod);
            }
        }
    }

    // 寻找(MainActivity.class)订阅方法集合,参考SubscriberMethodFinder.java 55行
    private List<SubscriberMethod> findSubscriberMethods(Class<?> subscriberClass) {
        // 从方法缓存中读取
        List<SubscriberMethod> subscriberMethods = METHOD_CACHE.get(subscriberClass);
        // 找到了缓存,直接返回
        if (subscriberMethods != null) {
            return subscriberMethods;
        }
        // 找不到,从APT生成的类文件中寻找
        subscriberMethods = findUsingInfo(subscriberClass);
        if (subscriberMethods != null) {
            // 存入缓存
            METHOD_CACHE.put(subscriberClass, subscriberMethods);
        }
        return subscriberMethods;
    }

    // 遍历中……并开始订阅,参考EventBus.java 149行
    private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) {
        // 获取订阅方法参数类型,如:UserInfo.class
        Class<?> eventType = subscriberMethod.getEventType();
        // 临时对象存储
        Subscription subscription = new Subscription(subscriber, subscriberMethod);
        // 读取EventBean缓存
        CopyOnWriteArrayList<Subscription> subscriptions = subscriptionsByEventType.get(eventType);
        if (subscriptions == null) {
            // 初始化集合
            subscriptions = new CopyOnWriteArrayList<>();
            // 存入缓存
            subscriptionsByEventType.put(eventType, subscriptions);
        } else {
            if (subscriptions.contains(subscription)) {
                Log.e("netease >>> ", subscriber.getClass() + "重复注册粘性事件!");
                // 执行多次粘性事件,但不添加到集合,避免订阅方法多次执行
                sticky(subscriberMethod, eventType, subscription);
                return;
            }
        }

        // 订阅方法优先级处理。第一次进来肯定是0,参考EventBus.java 163行
        int size = subscriptions.size();
        // 这里的i <= size,否则进不了下面条件
        for (int i = 0; i <= size; i++) {
            // 如果满足任一条件则进入循环(第1次 i = size = 0)
            // 第2次,size不为0,新加入的订阅方法匹配集合中所有订阅方法的优先级
            if (i == size || subscriberMethod.getPriority() > subscriptions.get(i).subscriberMethod.getPriority()) {
                // 如果新加入的订阅方法优先级大于集合中某订阅方法优先级,则插队到它之前一位
                if (!subscriptions.contains(subscription)) subscriptions.add(i, subscription);
                // 优化:插队成功就跳出(找到了加入集合点)
                break;
            }
        }

        // 订阅者类型集合,比如:订阅者MainActivity订阅了哪些EventBean,或者解除订阅的缓存
        List<Class<?>> subscribedEvents = typesBySubscriber.get(subscriber);
        if (subscribedEvents == null) {
            subscribedEvents = new ArrayList<>();
            // 存入缓存
            typesBySubscriber.put(subscriber, subscribedEvents);
        }
        // 注意:subscribe()方法在遍历过程中,所以一直在添加
        subscribedEvents.add(eventType);

        sticky(subscriberMethod, eventType, subscription);
    }

    // 抽取原因:可执行多次粘性事件,而不会出现闪退,参考EventBus.java 158行
    private void sticky(SubscriberMethod subscriberMethod, Class<?> eventType, Subscription subscription) {
        // 粘性事件触发:注册事件就**方法,因为整个源码只有此处遍历了。
        // 最佳切入点原因:1,粘性事件的订阅方法加入了缓存。2,注册时只有粘性事件直接**方法(隔离非粘性事件)
        // 新增开关方法弊端:粘性事件未在缓存中,无法触发订阅方法。且有可能多次执行post()方法
        if (subscriberMethod.isSticky()) { // 参考EventBus.java 178行
            // 源码中做了继承关系的处理,也说明了迭代效率和更改数据结构方便查找,这里就省略了(真实项目极少)
            Object stickyEvent = stickyEvents.get(eventType);
            // 发送事件 到 订阅者的所有订阅方法,并**方法
            if (stickyEvent != null) postToSubscription(subscription, stickyEvent);
        }
    }

    // 从APT生成的类文件中寻找订阅方法集合,参考SubscriberMethodFinder.java 64行
    private List<SubscriberMethod> findUsingInfo(Class<?> subscriberClass) {
        // app在运行时寻找索引,报错了则说明没有初始化索引方法
        if (subscriberInfoIndexes == null) {
            throw new RuntimeException("未添加索引方法:addIndex()");
        }
        // 接口持有实现类的引用
        SubscriberInfo info = subscriberInfoIndexes.getSubscriberInfo(subscriberClass);
        // 数组转List集合,参考EventBus生成的APT类文件
        if (info != null) return Arrays.asList(info.getSubscriberMethods());
        return null;
    }

    // 是否已经注册 / 订阅,参考EventBus.java 217行
    public synchronized boolean isRegistered(Object subscriber) {
        return typesBySubscriber.containsKey(subscriber);
    }

    // 解除某订阅者关系,参考EventBus.java 239行
    public synchronized void unregister(Object subscriber) {
        // 从缓存中移除
        List<Class<?>> subscribedTypes = typesBySubscriber.get(subscriber);
        if (subscribedTypes != null) {
            // 移除前清空集合
            subscribedTypes.clear();
            typesBySubscriber.remove(subscriber);
        }
    }

    // 发送粘性事件,最终还是调用了post方法,参考EventBus.java 301行
    public void postSticky(Object event) {
        // 同步锁保证并发安全(小项目可忽略此处)
        synchronized (stickyEvents) {
            // 加入粘性事件缓存集合
            stickyEvents.put(event.getClass(), event);
        }
        // 巨坑!!!源码这么写我也不知道什么意图。恶心的后果:只要参数匹配,粘性/非粘性订阅方法全部执行
        // post(event);
    }

    // 获取指定类型的粘性事件,参考EventBus.java 314行
    public <T> T getStickyEvent(Class<T> eventType) {
        // 同步锁保证并发安全(小项目可忽略此处)
        synchronized (stickyEvents) {
            // cast方法做转换类型时安全措施(简化stickyEvents.get(eventType))
            return eventType.cast(stickyEvents.get(eventType));
        }
    }

    // 移除指定类型的粘性事件(此处返回值看自己需求,可为boolean),参考EventBus.java 325行
    public <T> T removeStickyEvent(Class<T> eventType) {
        // 同步锁保证并发安全(小项目可忽略此处)
        synchronized (stickyEvents) {
            return eventType.cast(stickyEvents.remove(eventType));
        }
    }

    // 移除所有粘性事件,参考EventBus.java 352行
    public void removeAllStickyEvents() {
        // 同步锁保证并发安全(小项目可忽略此处)
        synchronized (stickyEvents) {
            // 清理集合
            stickyEvents.clear();
        }
    }

    // 发送消息 / 事件
    public void post(Object event) {
        // 此处两个参数,简化了源码,参考EventBus.java 252 - 265 - 384 - 400行
        postSingleEventForEventType(event, event.getClass());
    }

    // 为EventBean事件类型发布单个事件(遍历),EventBus核心:参数类型必须一致!!!
    private void postSingleEventForEventType(Object event, Class<?> eventClass) {
        // 从EventBean缓存中,获取所有订阅者和订阅方法
        CopyOnWriteArrayList<Subscription> subscriptions;
        synchronized (this) {
            // 同步锁,保证并发安全
            subscriptions = subscriptionsByEventType.get(eventClass);
        }
        // 判空,健壮性代码
        if (subscriptions != null && !subscriptions.isEmpty()) {
            for (Subscription subscription : subscriptions) {
                // 遍历,寻找发送方指定的EventBean,匹配的订阅方法的EventBean
                postToSubscription(subscription, event);
            }
        }
    }

    // 发送事件 到 订阅者的所有订阅方法(遍历中……),参考参考EventBus.java 427行
    private void postToSubscription(final Subscription subscription, final Object event) {
        // 匹配订阅方的线程模式
        switch (subscription.subscriberMethod.getThreadMode()) {
            case POSTING: // 订阅、发布在同一线程
                invokeSubscriber(subscription, event);
                break;
            case MAIN:
                // 订阅方是主线程,则主 - 主
                if (Looper.myLooper() == Looper.getMainLooper()) {
                    invokeSubscriber(subscription, event);
                } else {
                    // 订阅方是子线程,则子 - 主
                    handler.post(new Runnable() {
                        @Override
                        public void run() {
                            invokeSubscriber(subscription, event);
                        }
                    });
                }
                break;
            case ASYNC:
                // 订阅方是主线程,则主 - 子
                if (Looper.myLooper() == Looper.getMainLooper()) {
                    // 主线程 - 子线程,创建一个子线程(缓存线程池)
                    executorService.execute(new Runnable() {
                        @Override
                        public void run() {
                            invokeSubscriber(subscription, event);
                        }
                    });
                } else {
                    // 订阅方是子线程,则子 - 子
                    invokeSubscriber(subscription, event);
                }
                break;
            default:
                throw new IllegalStateException("未知线程模式!" + subscription.subscriberMethod.getThreadMode());
        }
    }

    // 执行订阅方法(被注解方法自动执行)参考EventBus.java 505行
    private void invokeSubscriber(Subscription subscription, Object event) {
        try {
            // 无论3.0之前还是之后。最后一步终究逃不过反射!
            subscription.subscriberMethod.getMethod().invoke(subscription.subscriber, event);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    // 清理静态缓存(视项目规模调用)
    public static void clearCaches() {
        METHOD_CACHE.clear();
    }
}

javaPoet生成的类文件格式为:

public final class EventBusIndex implements SubscriberInfoIndex {
  private static final Map<Class, SubscriberInfo> SUBSCRIBER_INDEX;

  static {
    SUBSCRIBER_INDEX = new HashMap<Class, SubscriberInfo>();
    putIndex(new EventBeans(MainActivity.class, new SubscriberMethod[] {
      new SubscriberMethod(MainActivity.class, "handleMessageEvent", MessageEvent.class, ThreadMode.MAIN, 0, false)} ));
  }

  private static void putIndex(SubscriberInfo info) {
    SUBSCRIBER_INDEX.put(info.getSubscriberClass(), info);
  }

  @Override
  public SubscriberInfo getSubscriberInfo(Class subscriberClass) {
    return SUBSCRIBER_INDEX.get(subscriberClass);
  }
}

源码传送门