美文网首页
EventBus 3.2.0 源码阅读

EventBus 3.2.0 源码阅读

作者: 河里的枇杷树 | 来源:发表于2020-06-17 09:28 被阅读0次

    版本

    v3.2.0

    源码+注释存放在

    参考:

    读前简介

    1. EventBus中的各个角色

    • 发布者
    • 订阅者
    • 订阅方法
    • 事件
    • 发布线程
    • 订阅线程
    • 事件Hash表

    2.主要类功能及名词介绍

    • SubscriberMethod:订阅方法的封装
    • EventBus : EventBus框架的入口,提供 注册,反注册 ,发送消息,配置能力
    • EventBusBuilder:EventBus的构建器
    • SubscriberMethodFinder:订阅方法查找器 ,用于获取
    • Subscription:作为一个订阅的封装 ,拥有订阅者 和 订阅方法
    • HandlerPoster:一个Handler 如果 传入looper 是主线程 那就是主线程 handler
    • 黏性事件:就是在发送事件之后再订阅该事件也能收到该事件,用于解决异步所带来的一些问题

    源码阅读顺序

    1. 获取EventBus实例
    2. 注册 及 注册订阅方法
    3. 反注册
    4. 发送消息 及 接受消息
    5. 取消事件
    6. 黏性事件
    7. 线程切换

    下面我们就按照这个顺序,依次看一下EventBus 都做了哪些事情

    开始阅读

    一. 获取EventBus实例

    1. EventBus.getDefault()

    EventBus.getDefault()就是通过 DCL 方式 创建单例。通过这种方式获取的消息线路,我们称之为 ==消息总线==

        static volatile EventBus defaultInstance;
    
        //使用DCL 方式创建单例 
        public static EventBus getDefault() {
            EventBus instance = defaultInstance;
            if (instance == null) {
                synchronized (EventBus.class) {
                    instance = EventBus.defaultInstance;
                    if (instance == null) {
                        instance = EventBus.defaultInstance = new EventBus();
                    }
                }
            }
            return instance;
        }
    
    2. new EventBus()

    除了使用 EventBus.getDefault() 获取单例 以外,EventBus 还支持通过 new 的方式创建新的EventBus 对象,不过不同的EventBus 对象对应着不同的 消息线路,也就是说 ==A== EventBus 不可能 接收到 ==B== EventBus 的 消息。所以如果总线压力过大,我们可以 通过多个EventBus 来分担 总线的压力.

    3. new EventBus(EventBusBuilder builder)

    除了使用默认构造这种简单的创建方式以外,EventBus 还支持通过 构建器来创建 实例。其实默认构造最终也是调用的构建器模式,只不过它的构建器也是默认的。如下代码所示

        private static final EventBusBuilder DEFAULT_BUILDER = new EventBusBuilder();
        
        public EventBus() {
            this(DEFAULT_BUILDER);
        }
    
        EventBus(EventBusBuilder builder) {
        .....
        }
    

    下来我们看看怎么通过构建器创建EventBus 对象

      EventBusBuilder builder = EventBus.builder();
            builder.eventInheritance=false;
            builder. ..
            EventBus eventBus = builder.installDefaultEventBus();
            eventBus. ..
    

    其实就是通过 构建器 设置一些默认的值 ,然后在构建出一个 EventBus 对象。非常正统的构建器模式。下来我们看一下 EventBus 都给我们预留了那些 接口。可以让我们自行配置。

    4. EventBusBuilder 配置
    属性---含义---默认值的对应关系(具体功能介绍请看下方)
    属性 含义 默认值
    logSubscriberExceptions 订阅函数执行有异常时,打印异常信息 true
    logNoSubscriberMessages 是否打印没有 订阅函数 的log true
    sendSubscriberExceptionEvent 订阅函数执行出错 是是否发送 一个异常类型为 SubscriberExceptionEvent 的消息 方便统一常 true
    sendNoSubscriberEvent 没有对应订阅函数是发送一个类型为 NoSubscriberEvent 的消息 方便统一 true
    throwSubscriberException 订阅函数执行出错时抛出 EventBusException 异常,当为true时 logSubscriberExceptions,sendSubscriberExceptionEvent 这俩就没用了 false
    eventInheritance 是否触发 订阅函数形参 为消息类型的父类的订阅函数(官方描述 如果关闭会 提升20的速度,具体时间取决于 注册类的继承结构) true
    ignoreGeneratedIndex 忽略订阅者索引(既是存在订阅者索引,也强制使用反射获取订阅方法) false
    strictMethodVerification 是否严格验证订阅函数签名 false
    executorService 自定义线程池 DEFAULT_EXECUTOR_SERVICE
    skipMethodVerificationForClasses 跳过方法签名验证集合
    subscriberInfoIndexes 添加订阅者索引(不指定的话EventBus就会通过反射的方式获取 注册方法 列表)
    logger EventBus 内部使用的 Logger
    具体功能解析
    • logSubscriberExceptions:订阅函数执行有异常时,打印异常信息
      当为true是如果订阅函数内部异常的话 会在控制台打印 error 类型的log,如下log,如果为false则不打印。
    2020-06-15 11:58:11.380 26367-26367/org.greenrobot.eventbusperf E/EventBus: Could not dispatch event: class java.lang.String to subscribing class class org.greenrobot.debug.BadExceptionSubscriber
        java.lang.RuntimeException: Bad
            at org.greenrobot.debug.BadExceptionSubscriber.onEvent(BadExceptionSubscriber.java:8)
            at java.lang.reflect.Method.invoke(Native Method)
            at org.greenrobot.eventbus.EventBus.invokeSubscriber(EventBus.java:511)
            at org.greenrobot.eventbus.EventBus.postToSubscription(EventBus.java:434)
            .....
    
    • logNoSubscriberMessages : 是否打印没有监听者的log
      当为true时:如果没有对应的监听者会在 控制台打印 如下log。如果为false就没有
    2020-06-15 11:02:43.656 14516-14516/org.greenrobot.eventbusperf D/EventBus: No subscribers registered for event class java.lang.String
    2020-06-15 11:02:43.656 14516-14516/org.greenrobot.eventbusperf D/EventBus: No subscribers registered for event class org.greenrobot.eventbus.NoSubscriberEvent
    
    • sendSubscriberExceptionEvent : 订阅函数执行出错 是是否发送 一个异常类型为 SubscriberExceptionEvent 的消息 方便统一处理异常
      当为true时遇到 订阅函数执行有异常的时候会发送一个异常类型为 SubscriberExceptionEvent 的消息。这时候我们可以进行降级处理 或者 上报异常 操作如下
      @Subscribe(threadMode = ThreadMode.MAIN)
        public void onEvent(SubscriberExceptionEvent event) {
            Log.e(TAG,"订阅函数有异常 "+event.toString());
    
        }
    
    • sendNoSubscriberEvent: 没有对应订阅函数是发送一个类型为 NoSubscriberEvent 的消息 。这时候我们可以进行降级处理 或者 上报异常 操作如下
      @Subscribe(threadMode = ThreadMode.MAIN)
        public void onEvent(NoSubscriberEvent event) {
            Log.e(TAG,"没有订阅函数 "+event.toString());
    
        }
    
    • throwSubscriberException:订阅函数执行出错时抛出 EventBusException 异常,当为true时 logSubscriberExceptions,sendSubscriberExceptionEvent 这俩就没用了,因为在 EventBus 中如下代码中 throwSubscriberException 的优先级比 logSubscriberExceptions,sendSubscriberExceptionEvent 这俩高
     private void handleSubscriberException(Subscription subscription, Object event, Throwable cause) {
            if (event instanceof SubscriberExceptionEvent) {
                ....
            } else {
                if (throwSubscriberException) {
                    throw new EventBusException("Invoking subscriber failed", cause);
                }
                if (logSubscriberExceptions) {
                    logger.log(Level.SEVERE, "Could not dispatch event: " + event.getClass() + " to subscribing class "
                            + subscription.subscriber.getClass(), cause);
                }
                if (sendSubscriberExceptionEvent) {
                    SubscriberExceptionEvent exEvent = new SubscriberExceptionEvent(this, cause, event,
                            subscription.subscriber);
                    post(exEvent);
                }
            }
        }
    
    • eventInheritance :是否触发 订阅函数形参 为消息类型的父类的订阅函数(有点绕,看下面例子就很清晰)官方描述 如果关闭会 提升20的速度,具体时间取决于 注册类的继承结构。
      
          // BEventBean 继承了 AEventBean
          public class BEventBean extends AEventBean {
              public String bMsg;
          }
      
      
          @Subscribe(threadMode = ThreadMode.MAIN)
          public void onEventStr(AEventBean msg) {
              log(msg.toString());
          }
      
      
          @Subscribe(threadMode = ThreadMode.MAIN)
          public void onEventStr(BEventBean msg) {
              toast(msg.toString());
          }
      
      ==注: BEventBean 继承了 AEventBean==
      • 当 eventInheritance 为true的时候上面 两个订阅方法都会被执行。
      • 当 eventInheritance 为false的时候只有形参为 BEventBean 会被执行。
    • ignoreGeneratedIndex:即使存在订阅者索引,也强制使用反射获取订阅方法。
      这个标示位使用在SubscriberMethodFinder.findSubscriberMethods 方法中.
       List<SubscriberMethod> findSubscriberMethods(Class<?> subscriberClass) {
            List<SubscriberMethod> subscriberMethods = METHOD_CACHE.get(subscriberClass);
            if (subscriberMethods != null) {
                return subscriberMethods;
            }
    
            if (ignoreGeneratedIndex) {
                subscriberMethods = findUsingReflection(subscriberClass);
            } else {
                subscriberMethods = findUsingInfo(subscriberClass);
            }
            if (subscriberMethods.isEmpty()) {
                throw new EventBusException("Subscriber " + subscriberClass
                        + " and its super classes have no public methods with the @Subscribe annotation");
            } else {
                METHOD_CACHE.put(subscriberClass, subscriberMethods);
                return subscriberMethods;
            }
        }
    
    • strictMethodVerification: 是否严格验证订阅函数签名,默认为false,当为true时 EventBus 当检测到 注册方法的签名不合法时会抛出异常,代码位于 SubscriberMethodFinder.findUsingReflectionInSingleClass
    • executorService:可以设置项目自己的线程池 如果有的话 ,避免 项目中有多个箱尺寸在,浪费资源
    • skipMethodVerificationForClasses :跳过方法签名验证集合,通过 skipMethodVerificationFor(Class<?> clazz) 可以添加
    • subscriberInfoIndexes:添加订阅者索引,方便我们自定义和扩展
    • logger:EventBus 内部使用的 Logger ,可以使用 logger()方法进行设置

    二. 注册 及 注册订阅方法

    主要作用

    1. 查找订阅者中的订阅方法并缓存到 EventBus.subscriptionsByEventType 这个map中
    2. 如果是黏性订阅方法 订阅以后直接 调用。以实现先 发消息后注册 也能接收到 事件的功能

    源码梳理

    1. EventBus.register
        //注册 订阅者
        public void register(Object subscriber) {
            //获取接受者的字节码对象
            Class<?> subscriberClass = subscriber.getClass();
            //查找 subscriber 中的订阅方法 ,这里没有加锁 说明可以并发进行 【详见1.1】
            List<SubscriberMethod> subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass);
            synchronized (this) {
                //遍历所有订阅方法
                for (SubscriberMethod subscriberMethod : subscriberMethods) {
                    //预处理每个 订阅方法 【详见1.2】
                    subscribe(subscriber, subscriberMethod);
                }
            }
        }
    
    1.1 SubscriberMethodFinder.findSubscriberMethods

    主要作用是 在订阅者中查找订阅方法列表 并进行返回,查找方式分为两种

    1. 反射
    2. 订阅索引

    使用订阅索引会提高EventBus的运行速度,具体原理和如何使用参考 ==知识点3,4==

     List<SubscriberMethod> findSubscriberMethods(Class<?> subscriberClass) {
            //从缓存中获取
            List<SubscriberMethod> subscriberMethods = METHOD_CACHE.get(subscriberClass);
            if (subscriberMethods != null) {
                //命中缓存直接返回
                return subscriberMethods;
            }
    
            //是否强制使用反射获取订阅方法(可在EventBusBuilder 中配置)
            if (ignoreGeneratedIndex) {//使用反射
                subscriberMethods = findUsingReflection(subscriberClass);
            } else {//使用索引查找
                subscriberMethods = findUsingInfo(subscriberClass);
            }
            if (subscriberMethods.isEmpty()) {
                throw new EventBusException("Subscriber " + subscriberClass
                        + " and its super classes have no public methods with the @Subscribe annotation");
            } else {
                METHOD_CACHE.put(subscriberClass, subscriberMethods);
                return subscriberMethods;
            }
        }
    
    1.2 EventBus.subscribe

    主要有两个

    1. 将订阅关系缓存到 subscriptionsByEventType 和 typesBySubscriber中
    2. 如果是黏性事件 直接调用 订阅方法
     private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) {
             ....
             //添加 订阅方法形参类型 和 一个订阅 的映射
             subscriptionsByEventType.put(eventType, subscriptions);
    
             ....
             //添加 订阅者 和 订阅方法形参类型 的映射
             typesBySubscriber.put(subscriber, subscribedEvents);
             
             ....
    
            //如果是黏性订阅方法 订阅以后直接 调用,
            if (subscriberMethod.sticky) {
                //是否触发 订阅函数形参 为消息类型的父类的订阅函数,可在 EventBusBuilder 中配置
                if (eventInheritance) {//是
    
                    Set<Map.Entry<Class<?>, Object>> entries = stickyEvents.entrySet();
                    for (Map.Entry<Class<?>, Object> entry : entries) {
                        Class<?> candidateEventType = entry.getKey();
                        //candidateEventType 是否是 eventType 的子类
                        if (eventType.isAssignableFrom(candidateEventType)) {
                            Object stickyEvent = entry.getValue();
                            checkPostStickyEventToSubscription(newSubscription, stickyEvent);
                        }
                    }
                } else {//否
                    Object stickyEvent = stickyEvents.get(eventType);
                    checkPostStickyEventToSubscription(newSubscription, stickyEvent);
                }
            }
        }
    

    三. 反注册

    主要作用

    主要作用是 将在订阅过程中形成的订阅关系同 缓存中清除 ,清除的位置有两个

    1. subscriptionsByEventType
    2. typesBySubscriber

    源码梳理

    1. EventBus.unregister
       public synchronized void unregister(Object subscriber) {
            List<Class<?>> subscribedTypes = typesBySubscriber.get(subscriber);
            if (subscribedTypes != null) {
                for (Class<?> eventType : subscribedTypes) {
                    //移除各个订阅
                    unsubscribeByEventType(subscriber, eventType);
                }
                // 移除 订阅者 和 订阅方法形参类型 的映射关系
                typesBySubscriber.remove(subscriber);
            } else {
                logger.log(Level.WARNING, "Subscriber to unregister was not registered before: " + subscriber.getClass());
            }
        }
    

    三. 发送消息 及 接受消息

    主要作用

    发送事件并触发订阅方法

    源码梳理

    1. EventBus.post
     public void post(Object event) {
            //获取到当前线程的 PostingThreadState(用 ThreadLocal 保存 所以每个 线程只有一个)
            PostingThreadState postingState = currentPostingThreadState.get();
            //获取当前线程的 事件队列
            List<Object> eventQueue = postingState.eventQueue;
            //将事件添加到事件队列中
            eventQueue.add(event);
    
            if (!postingState.isPosting) {//没有正在发送事件
                ....
                try {
                    while (!eventQueue.isEmpty()) {//队列不为空
                        //发送事件 【详见1.1】
                        postSingleEvent(eventQueue.remove(0), postingState);
                    }
                } finally {//重置状态
                    postingState.isPosting = false;
                    postingState.isMainThread = false;
                }
            }
        }
    
    
    1.1 EventBus.postSingleEvent
     private void postSingleEvent(Object event, PostingThreadState postingState) throws Error {
            //获取事件类型
            Class<?> eventClass = event.getClass();
            boolean subscriptionFound = false;
            //是否 触发 event 父类的 注册方法
            if (eventInheritance) {
                List<Class<?>> eventTypes = lookupAllEventTypes(eventClass);
                int countTypes = eventTypes.size();
                for (int h = 0; h < countTypes; h++) {
                    Class<?> clazz = eventTypes.get(h);
                    //【详见1.2】
                    subscriptionFound |= postSingleEventForEventType(event, postingState, clazz);
                }
            } else {
                //【详见1.2】
                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) {
                    //发送一个 NoSubscriberEvent
                    post(new NoSubscriberEvent(this, event));
                }
            }
        }
    
    
    1.2 EventBus.postSingleEventForEventType
    private boolean postSingleEventForEventType(Object event, PostingThreadState postingState, Class<?> eventClass) {
            CopyOnWriteArrayList<Subscription> subscriptions;
            synchronized (this) {
                //通过 订阅方法形参类型 获取 订阅列表
                subscriptions = subscriptionsByEventType.get(eventClass);
            }
            if (subscriptions != null && !subscriptions.isEmpty()) {//查找到了
                for (Subscription subscription : subscriptions) {
                    postingState.event = event;
                    postingState.subscription = subscription;
                    boolean aborted;
                    try {
                        //触发所有订阅方法 【详见1.3】
                        postToSubscription(subscription, event, postingState.isMainThread);
                         // 执行 cancelEventDelivery 后 postingState.canceled 会为true
                        aborted = postingState.canceled;
                    } finally {
                        postingState.event = null;
                        postingState.subscription = null;
                        postingState.canceled = false;
                    }
                    //如果执行了 cancelEventDelivery 就会退出,不在 触发其他订阅方法
                    if (aborted) {
                        break;
                    }
                }
                return true;
            }
            return false;
        }
    
    
    1.3 EventBus.postToSubscription
     private void postToSubscription(Subscription subscription, Object event, boolean isMainThread) {
            switch (subscription.subscriberMethod.threadMode) {
                case POSTING://直接触发
                    invokeSubscriber(subscription, event);
                    break;
                case MAIN://如果不是主线程 切换到主线程触发
                    if (isMainThread) {
                        //详见【1.4】
                        invokeSubscriber(subscription, event);
                    } else {//不是主线程的话 会 通过handle调度到主线程执行
                        //详见【1.5】
                        mainThreadPoster.enqueue(subscription, event);
                    }
                    break;
                case MAIN_ORDERED:
                    if (mainThreadPoster != null) {
                        mainThreadPoster.enqueue(subscription, event);
                    } else {
                        // temporary: technically not correct as poster not decoupled from subscriber
                        invokeSubscriber(subscription, event);
                    }
                    break;
                case BACKGROUND:
                    if (isMainThread) {
                        backgroundPoster.enqueue(subscription, event);
                    } else {
                        invokeSubscriber(subscription, event);
                    }
                    break;
                case ASYNC:
                    asyncPoster.enqueue(subscription, event);
                    break;
                default:
                    throw new IllegalStateException("Unknown thread mode: " + subscription.subscriberMethod.threadMode);
            }
        }
    
    1.4 EventBus.invokeSubscriber
        void invokeSubscriber(Subscription subscription, Object event) {
            try {
                //反射执行 订阅方法
                subscription.subscriberMethod.method.invoke(subscription.subscriber, event);
            } catch (InvocationTargetException e) {
                handleSubscriberException(subscription, event, e.getCause());
            } catch (IllegalAccessException e) {
                throw new IllegalStateException("Unexpected exception", e);
            }
        }
    
    1.5 HandlerPoster.enqueue
        public void enqueue(Subscription subscription, Object event) {
            //将 subscription , event 封装为 PendingPost
            PendingPost pendingPost = PendingPost.obtainPendingPost(subscription, event);
            synchronized (this) {
                //加入到队列中
                queue.enqueue(pendingPost);
                if (!handlerActive) {
                    handlerActive = true;
                    //使用handler 发送一个消息 【详见1.6】
                    if (!sendMessage(obtainMessage())) {
                        throw new EventBusException("Could not send handler message");
                    }
                }
            }
        }
    
    1.6 HandlerPoster.handleMessage
    
     @Override
        public void handleMessage(Message msg) {
            boolean rescheduled = false;
            try {
                long started = SystemClock.uptimeMillis();
                while (true) {
                    //取出一个 事件
                    PendingPost pendingPost = queue.poll();
                    ....
                    //执行 订阅方法 【详见1.4】
                    eventBus.invokeSubscriber(pendingPost);
                    ....
                }
            } finally {
                handlerActive = rescheduled;
            }
        }
    

    四. 取消事件

    主要作用

    取消以后就不会触发 后面的 订阅方法

    源码梳理

    1 HandlerPoster.cancelEventDelivery
     public void cancelEventDelivery(Object event) {
            PostingThreadState postingState = currentPostingThreadState.get();
            //只有  threadMode = POSTING 时有效
            if (!postingState.isPosting) {
                throw new EventBusException(
                        "This method may only be called from inside event handling methods on the posting thread");
            } else if (event == null) {
                throw new EventBusException("Event may not be null");
            } else if (postingState.event != event) {
                throw new EventBusException("Only the currently handled event may be aborted");
            } else if (postingState.subscription.subscriberMethod.threadMode != ThreadMode.POSTING) {
                throw new EventBusException(" event handlers may only abort the incoming event");
            }
    
            //更改 canceled 为true
            postingState.canceled = true;
        }
    

    其实只是将 postingState.canceled 标志位 设置为 true,生效的地方参见 【==发送消息 及 接受消息 中1.2 postSingleEventForEventType==】

    五. 黏性事件

    主要作用

    添加一个黏性事件,用于解决异步的一些问题

    源码梳理

    1 HandlerPoster.postSticky
        public void postSticky(Object event) {
            synchronized (stickyEvents) {
                stickyEvents.put(event.getClass(), event);
            }
            // 先触发一次
            post(event);
        }
    

    发送黏性时间后 会先将事件保存到 stickyEvents 中,然后立马触发一次。当以后有黏性 订阅方法订阅后 会立即执行这个黏性事件,这也是为啥 黏性事件可以先发送再注册 也能接收到的原理。==黏性事件触发位置参考 【注册 及 注册订阅方法中1.2 EventBus.subscribe】==

    六. 线程切换

    主要作用

    通过不同的 ThreadMode 指定 线程

    源码梳理

    【参考 发送消息 及 接受消息 中 1.3 EventBus.postToSubscription】
    • POSTING :默认值,那个线程发送消息就是那个线程接受消息
    • MAIN:指定主线程接受消息
    • MAIN_ORDERED:也是指定主线程接受消息,不过如果前一个也是main_ordered 则需要等前一个执行完成后才执行
    • BACKGROUND:指定后台线程(只有一个 ),处理如保存到数据库等操作。
    • ASYNC:接受是始终重启进程进行操作,一般是用于比较消耗时间的任务

    总结

    流程分析

    1. 获取实例步骤 过程中我们可以对EventBus做一些配置
    2. 订阅 步骤只是对订阅者及订阅方法映射的缓存,如果是黏性事件则立即触发 订阅方法
    3. 反订阅 步骤就是 删除订阅步骤缓存的映射
    4. 发送消息 及 接受消息 步骤就是: 通过订阅步骤中生成的缓存 查找到 对应方法并 对于不同的 ThreadMode ,做不同的线程切换,最后都调用对应的 订阅方法。
    5. 取消事件就相当于 停止 下一个 订阅方法的执行。

    ThreadMode的几种模式

    • POSTING :默认值,那个线程发送消息就是那个线程接受消息
    • MAIN:指定主线程接受消息
    • MAIN_ORDERED:也是指定主线程接受消息,不过如果前一个也是main_ordered 则需要等前一个执行完成后才执行
    • BACKGROUND:指定后台线程(只有一个 ),处理如保存到数据库等操作。
    • ASYNC:接受是始终重启进程进行操作,一般是用于比较消耗时间的任务

    知识点

    1. ==其实 Java中也有观察者模式的实现(Observer,Observable),其工作原理和 EventBus很像,只不过 EventBus 使用起来更加方便而且具有线程切换等优点。==

    2. 在某些情况下,比如 Activity中 getDeclaredMethods 比 getMethods 快,因为 getDeclaredMethods 只获取自身的方法(public、protected、private),而getMethods 会向上查找 所有父类的方法(public)。

    3. 查找订阅方法重如果我们没有手动设置过 EventBusBuilder 的 subscriberInfoIndexes 那么就会通过反射获取 注册方法 列表, 所以我们再使用EventBus 的时候最好通过builder指定一下 subscriberInfoIndexes,毕竟 反射 是比较耗时的。代码如下

          EventBus  eventBus = EventBus.builder()
                    .addIndex(new MyEventBusIndex())
                    .installDefaultEventBus();
    
    1. SubscriberMethodFinder中 使用反射获取 订阅方法列表和 通过 订阅索引获取 订阅方法列表 本质的区别是前者是在运行期 才组织关系,而 后者是在编译器 就已经确定。所以使用后者会 提高 运行速度。

    相关文章

      网友评论

          本文标题:EventBus 3.2.0 源码阅读

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