EventBus用法和源码解析
            
         
        
        
        
        
            本文于
                1701 
            天之前发表,文中内容可能已经过时。
        
        
     
    
    
        [TOC]
参照版本:
EventBus 3.0以后
为什么选择EventBus 
简化了 组件交流方式 
对事件通信双方解耦 
灵活指定线程(4种线程模式) 
速度快,性能好 
库比较小,不占内存 
使用方便 
 
使用指南 
角色 
Event :事件 
Subscriber :事件订阅者 
Publisher :事件发布者 
 
五种线程模式 
POSTING :默认,发布和订阅在同一个线程 
MAIN :事件处理函数的线程在主线程(UI)线程。不能进行耗时操作,订阅者需快速返回以免阻塞主线程 
MAIN_ORDERED :事件处理函数的线程在主线程(UI)线程。不能进行耗时操作,不会阻塞线程 
BACKGROUND :处理函数在后台线程,不能进行UI操作。发布在主线程,订阅会开启一个新的后台线程。发布在后台线程,事件处理函数也在该后台线程 
ASYNC :无论事件发布的线程是哪一个,都会重新开辟一个新的子线程运行,不能进行UI操作 
 
MAIN和MAIN_ORDERED区别 
在MAIN模式下,如果事件发布者post事件也是在主线程的话,会阻塞post事件所在的线程,意思是连续post多个事件,如果接收事件方法执行完,才能post下一个事件 
 
         post(1) ——> onReceiveMsg(1) ——>post(2)——>onReceiveMsg(2)——>post(3)——>onReceiveMsg(3) 
如果事件发布者post事件不在主线程,连续post多个事件,同事在主线程是接收事件是耗时操作的话,执行的流程是非阻塞的 
 
         post(1)——>post(2)——>psot(3)——>onReceiveMsg(3)           或          post(1)——>post(2)——>psot(3)——>onReceiveMsg(2)——>onReceiveMsg(3) 
MAIN_ORDERED模式下,无论什么场景都是非阻塞的 
 
 
事件类型 普通事件 :注册和反注册后,发送EventBus.post()事件,在需要接收的地方使用@Subscribe方法,方法必须是public
粘性事件 :注册和反注册后,发送EventBus.postSticky()黏性事件,在需要接收的地方使用@Subscribe方法,方法必须是public,添加sticky = true
普通事件是先订阅后发送,粘性事件支持先发送后订阅
 
优先级 说明:优先级高的订阅者优先接收到任务
threadMode参数相同 
只有走到threadMode参数为POSTING的时候才会停止该事件的继续分发,调用cancelEventDelivery(xx) 
 
混淆 1 2 3 4 5 6 7 8 9 10 -keepattributes *Annotation* -keepclassmembers class ** {     @org.greenrobot.eventbus.Subscribe <methods>; } -keep enum org.greenrobot.eventbus.ThreadMode { *; } # Only required if you use AsyncExecutor -keepclassmembers class * extends org.greenrobot.eventbus.util.ThrowableFailureEvent {     <init>(java.lang.Throwable); } 
 
索引 目的:
如何使用:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 android {     defaultConfig {         javaCompileOptions {             annotationProcessorOptions {                 arguments = [ eventBusIndex : 'com.example.myapp.MyEventBusIndex'  ]              }         }     } } dependencies {     implementation 'org.greenrobot:eventbus:3.1.1'      annotationProcessor 'org.greenrobot:eventbus-annotation-processor:3.1.1'  } 
 
在\app\build\generated\source\apt\debug\package\下可查看生成的MyEventBusIndex文件
在Application中使用
1 2 3 4 5 6 7 8 public  class  MyApplication  extends  Application  {    @Override      public  void  onCreate ()  {         super .onCreate();         EventBus.builder().addIndex(new  MyEventBusIndex ()).installDefaultEventBus();     } } 
 
如果想在整个应用使用默认实例
1 2 3 EventBus.builder().addIndex(new  MyEventBusIndex ()).installDefaultEventBus(); EventBus  eventBus  =  EventBus.getDefault();
 
源码解析 
注册流程
1 2 3 4 5 6 7 8 9 10 11     public  static  EventBus getDefault ()  {         if  (defaultInstance == null ) {             synchronized  (EventBus.class) {                 if  (defaultInstance == null ) {                     defaultInstance = new  EventBus ();                 }             }         }         return  defaultInstance;     } 
 
getDefault使用单例模式,保证整个app只有唯一实例。初次进入会进入无参构造中初始化
1 2 3 4 5 6 7 public  EventBus ()  {    this (DEFAULT_BUILDER); } 
 
1 private  static  final  EventBusBuilder  DEFAULT_BUILDER  =  new  EventBusBuilder ();
 
由此可以看出来DEFAULT_BUILDED是EventBusBuilder实例,具体的初始化在下面这个方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 EventBus(EventBusBuilder builder) {     logger = builder.getLogger();     subscriptionsByEventType = new  HashMap <>();     typesBySubscriber = new  HashMap <>();     stickyEvents = new  ConcurrentHashMap <>();     mainThreadSupport = builder.getMainThreadSupport();     mainThreadPoster = mainThreadSupport != null  ? mainThreadSupport.createPoster(this ) : null ;     backgroundPoster = new  BackgroundPoster (this );     asyncPoster = new  AsyncPoster (this );     indexCount = builder.subscriberInfoIndexes != null  ? builder.subscriberInfoIndexes.size() : 0 ;     subscriberMethodFinder = new  SubscriberMethodFinder (builder.subscriberInfoIndexes,             builder.strictMethodVerification, builder.ignoreGeneratedIndex);     logSubscriberExceptions = builder.logSubscriberExceptions;     logNoSubscriberMessages = builder.logNoSubscriberMessages;     sendSubscriberExceptionEvent = builder.sendSubscriberExceptionEvent;     sendNoSubscriberEvent = builder.sendNoSubscriberEvent;     throwSubscriberException = builder.throwSubscriberException;     eventInheritance = builder.eventInheritance;     executorService = builder.executorService; } 
 
初始化配置,部分配置从builder中获取,这是典型的建造者模式,查看EventBusBuilder类
1 2 3 4 public  EventBus build ()  {    return  new  EventBus (this ); } 
 
查看EventBus类
1 2 3 public  static  EventBusBuilder builder ()  {    return  new  EventBusBuilder (); } 
 
所以用两种初始化的方法:
EventBus.builder().build(); 
EventBus.getDefault() 
 
EventBusBuilder中配置如下
成员变量 
 
logSubscriberExceptions :是否打印订阅者异常信息,默认开启 
logNoSubscriberMessages :某个事件没有订阅者时,是否打印信息,默认开启 
sendSubscriberExceptionEvent :出现订阅者异常时,是否发送异常事件,默认开启 
sendNoSubscriberEvent :某个事件没有订阅者时,是否发送无订阅者的事件,默认开启 
throwSubscriberException :是否抛出订阅者异常信息,默认关闭 
eventInheritance :事件是否可以继承形式订阅,默认开启 
ignoreGeneratedIndex :忽略索引生成,默认关闭 
strictMethodVerification :是否开启方法严格验证,默认关闭 
executorService :线程池,默认是newCachedThreadPool,即没有核心线程、但最大线程数是Integer.MAX_VALUE的线程池 
skipMethodVerificationForClasses :跳过为订阅者类里面的方法进行校验,校验包括注解信息、修饰符是否是public且非static\final的,默认为空 
subscriberInfoIndexes :订阅者信息索引,由注解处理器生成 
mainThreadSupport :专为Android的主线程定制,持有主线程looper引用 
 
方法调用 
 
addIndex(SubscriberInfoIndex index):添加索引 
 
eventInheritance(boolean eventInheritance):是否支持事件继承
 
executorService(java.util.concurrent.ExecutorService executorService):提供用于一部和后台时间传递的自定义线程池
 
ignoreGeneratedIndex(boolean ignoreGeneratedIndex):强制使用反射,即使有生成的索引(默认值:false)。
 
skipMethodVerificationFor(java.lang.Class<?> clazz):对以onEvent开头的方法进行方法名验证,以避免键入错误;使用此方法,可以从此检查中排除订阅服务器类。
 
logNoSubscriberMessages(boolean logNoSubscriberMessages):当调用事件处理函数异常时是否打印异常信息
 
logSubscriberExceptions(boolean logSubscriberExceptions):当没有订阅者订阅该事件时是否打印日志
 
sendNoSubscriberEvent(boolean sendNoSubscriberEvent):当调用事件处理函数异常时是否发送 SubscriberExceptionEvent 事件,若此开关打开,订阅者可通过
1 public  void  onEvent (SubscriberExceptionEvent event) 
 
订阅该事件进行处理,默认为 true。
 
sendSubscriberExceptionEvent(boolean sendSubscriberExceptionEvent):当没有事件处理函数对事件处理时是否发送 NoSubscriberEvent 事件,若此开关打开,订阅者可通过
1 public  void  onEvent (NoSubscriberEvent event) 
 
订阅该事件进行处理,默认为 true。
 
strictMethodVerification**(boolean strictMethodVerification):启用严格的方法验证(默认值:false)。
 
throwSubscriberException**(boolean throwSubscriberException):如果订阅服务器引发异常,则失败(默认值:false)。
1 EventBus.builder().throwSubscriberException(true ).installDefaultEventBus() 
 
 
根据builder的默认配置统计得出:
当出现订阅者异常时,打印异常log 
当事件没有订阅者时,打印没有订阅者log 
当出现订阅者异常时,发送异常事件 
当事件没有订阅者时,发送无订阅者事件 
捕获异常信息,防止崩溃 
事件可以继承 
编译时生成索引 
采用最大限制是Integer.MAX_VALUE的缓存线程池 
为每个订阅者类都进行方法校验 
当处于Android平台时,确保可以切换到主线程 
 
自定义配置
1 2 3 EventBus.builder().logNoSubscriberMessages(false )                 .logSubscriberExceptions(false ).eventInheritance(false )...                 .installDefaultEventBus(); 
 
1 2 3 EventBus.builder().logNoSubscriberMessages(false )                 .logSubscriberExceptions(false ).eventInheritance(false )...                                 .build(); 
 
1 2 3 4 5 6 7 8 9 10 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;         }     } 
 
1 2 3 public  EventBus build ()  {        return  new  EventBus (this );     } 
 
installDefaultEventBus调用的也是build()方法,但是该方法多了一个单例,确保其全局的唯一性,所以使用build方法时需要自己维护其唯一性
注册 1 EventBus.getDefault().register(this); 
 
进入register方法
1 2 3 4 5 6 7 8 9 10 11 12 public  void  register (Object subscriber)  {               Class<?> subscriberClass = subscriber.getClass();                List<SubscriberMethod> subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass);        synchronized  (this ) {                        for  (SubscriberMethod subscriberMethod : subscriberMethods) {                subscribe(subscriber, subscriberMethod);            }        }    } 
 
SubscriberMethod是什么?
1 2 3 4 5 6 7 8 9 10 public  class  SubscriberMethod  {    final  Method method;        final  ThreadMode threadMode;       final  Class<?> eventType;        final  int  priority;        final  boolean  sticky;            String methodString;          ... } 
 
既然该事件是我们订阅方法的详细参数,那么他是从哪里来的,跟踪findSubscriberMethods
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 private  static  final  Map<Class<?>, List<SubscriberMethod>> METHOD_CACHE = new  ConcurrentHashMap <>();...... 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;         }     } 
 
从缓存中根据订阅者的class对象获取对应的所有订阅方法,继续跟踪subscribe()方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 private  void  subscribe (Object subscriber, SubscriberMethod subscriberMethod)  {               Class<?> eventType = subscriberMethod.eventType;        Subscription  newSubscription  =  new  Subscription (subscriber, subscriberMethod);                      CopyOnWriteArrayList<Subscription> subscriptions = subscriptionsByEventType.get(eventType);        if  (subscriptions == null ) {                        subscriptions = new  CopyOnWriteArrayList <>();            subscriptionsByEventType.put(eventType, subscriptions);        } else  {                        if  (subscriptions.contains(newSubscription)) {                throw  new  EventBusException ("Subscriber "  + subscriber.getClass() + " already registered to event "                         + eventType);            }        }                int  size  =  subscriptions.size();        for  (int  i  =  0 ; i <= size; i++) {            if  (i == size || subscriberMethod.priority > subscriptions.get(i).subscriberMethod.priority) {                subscriptions.add(i, newSubscription);                break ;            }        }                             List<Class<?>> subscribedEvents = typesBySubscriber.get(subscriber);        if  (subscribedEvents == null ) {                        subscribedEvents = new  ArrayList <>();            typesBySubscriber.put(subscriber, subscribedEvents);        }               subscribedEvents.add(eventType);        .....    } 
 
1 2 3 4 5 6 7 8 9 10 final  class  Subscription  {    final  Object subscriber;     final  SubscriberMethod subscriberMethod;          volatile  boolean  active;     ... } 
 
 Subscription为记录每个订阅方法和其对应的订阅者类,active在解注册的时候会被置为false,详看解注册
继续讲subscribe()方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 private  void  subscribe (Object subscriber, SubscriberMethod subscriberMethod)  {        ...                  if  (subscriberMethod.sticky) {                          if  (eventInheritance) {                                                                                                                                                         Set<Map.Entry<Class<?>, Object>> entries = stickyEvents.entrySet();                                  for  (Map.Entry<Class<?>, Object> entry : entries) {                     Class<?> candidateEventType = entry.getKey();                                          if  (eventType.isAssignableFrom(candidateEventType)) {                         Object  stickyEvent  =  entry.getValue();                         checkPostStickyEventToSubscription(newSubscription, stickyEvent);                     }                 }             } else  {                 Object  stickyEvent  =  stickyEvents.get(eventType);                 checkPostStickyEventToSubscription(newSubscription, stickyEvent);             }         } } 
 
如果是粘性事件,进入checkPostStickyEventToSubscription()方法中:
1 2 3 4 5 6 7 private  void  checkPostStickyEventToSubscription (Subscription newSubscription, Object stickyEvent)  {        if  (stickyEvent != null ) {                                       postToSubscription(newSubscription, stickyEvent, isMainThread());         }     } 
 
跳转到postToSubscription():
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 private  void  postToSubscription (Subscription subscription, Object event, boolean  isMainThread)  {                 switch  (subscription.subscriberMethod.threadMode) {             case  POSTING:                 invokeSubscriber(subscription, event);                 break ;             case  MAIN:                                  if  (isMainThread) {                     invokeSubscriber(subscription, event);                 } else  {                                          mainThreadPoster.enqueue(subscription, event);                 }                 break ;             case  MAIN_ORDERED:                                  if  (mainThreadPoster != null ) {                                          mainThreadPoster.enqueue(subscription, event);                 } else  {                                                               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);         }     }	 
 
最终的enqueue()方法都是调用的invokeSubscriber方法
总结:通过注解初始化订阅方法后,在register后,在缓存中获取所有该订阅者的方法,循环遍历订阅,新建newSubscription方法,根据priority优先级将newSubscription方法放入subscriptions中,判断如果是粘性事件,则执行其对应的订阅方法。
解注册 1 EventBus.getDefault().unregister(this); 
 
进入unregister方法
1 2 3 4 5 6 7 8 9 10 11 12 13 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());        }    } 
 
进入unsubscribeByEventType():
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 private  void  unsubscribeByEventType (Object subscriber, Class<?> eventType)  {                 List<Subscription> subscriptions = subscriptionsByEventType.get(eventType);         if  (subscriptions != null ) {             int  size  =  subscriptions.size();             for  (int  i  =  0 ; i < size; i++) {                 Subscription  subscription  =  subscriptions.get(i);                 if  (subscription.subscriber == subscriber) {                                          subscription.active = false ;                     subscriptions.remove(i);                     i--;                     size--;                 }             }         }     } 
 
总结:从typesBySubscriber获取订阅事件类型,根据订阅事件类型从subscriptionsByEventType获取订阅者信息,将subscription的active置为false,并移除该subscription
明显看出时regist的逆过程
typesBySubscriber :键是订阅者类,值是订阅事件类型的map
subscriptionsByEventType:键是订阅事件类型,值是订阅者信息
subscription:订阅信息,封装了订阅者类型和订阅方法,还有判断是否已经注册的active
 
发布普通事件 1 EventBus.getDefault().post(EventType type); 
 
进入post:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 public  void  post (Object event)  {                 PostingThreadState  postingState  =  currentPostingThreadState.get();                  List<Object> eventQueue = postingState.eventQueue;         eventQueue.add(event);                          if  (!postingState.isPosting) {                          postingState.isMainThread = isMainThread();                          postingState.isPosting = true ;                          if  (postingState.canceled) {                 throw  new  EventBusException ("Internal error. Abort state was not reset" );             }                          try  {                 while  (!eventQueue.isEmpty()) {                     postSingleEvent(eventQueue.remove(0 ), postingState);                 }             } finally  {                 postingState.isPosting = false ;                 postingState.isMainThread = false ;             }         }     } 
 
详看PostingThreadState是什么?
1 2 3 4 5 6 7 8 final  static  class  PostingThreadState  {        final  List<Object> eventQueue = new  ArrayList <>();             boolean  isPosting;                  boolean  isMainThread;               Subscription subscription;            Object event;                        boolean  canceled;             } 
 
PostingThreadState中包含了eventQueue和其他的标志位
进入postSingleEvent:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 private  void  postSingleEvent (Object event, PostingThreadState postingState)  throws  Error {               Class<?> eventClass = event.getClass();                boolean  subscriptionFound  =  false ;                if  (eventInheritance) {                        List<Class<?>> eventTypes = lookupAllEventTypes(eventClass);                        int  countTypes  =  eventTypes.size();            for  (int  h  =  0 ; h < countTypes; h++) {                Class<?> clazz = eventTypes.get(h);                                subscriptionFound |= postSingleEventForEventType(event, postingState, clazz);            }        } else  {                                    subscriptionFound = postSingleEventForEventType(event, postingState, eventClass);        }                if  (!subscriptionFound) {            if  (logNoSubscriberMessages) {                logger.log(Level.FINE, "No subscribers registered for event "  + eventClass);            }            if  (sendNoSubscriberEvent && eventClass != NoSubscriberEvent.class &&                    eventClass != SubscriberExceptionEvent.class) {                                post(new  NoSubscriberEvent (this , event));            }        }    } 
 
进入lookupAllEventTypes:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 private  static  final  Map<Class<?>, List<Class<?>>> eventTypesCache = new  HashMap <>();...... private  static  List<Class<?>> lookupAllEventTypes(Class<?> eventClass) {                 synchronized  (eventTypesCache) {                          List<Class<?>> eventTypes = eventTypesCache.get(eventClass);             if  (eventTypes == null ) {                                  eventTypes = new  ArrayList <>();                 Class<?> clazz = eventClass;                 while  (clazz != null ) {                     eventTypes.add(clazz);                     addInterfaces(eventTypes, clazz.getInterfaces());                                          clazz = clazz.getSuperclass();                 }                                  eventTypesCache.put(eventClass, eventTypes);             }             return  eventTypes;         }     } 
 
进入postSingleEventForEventType:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 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  =  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中,发送事件到订阅者,根据模式不同,不同处理
总结:事件可继承,获取事件所有超类,挨个发布信息,反之则发布信息,根据不同的模式,在不同线程中做处理。
发布粘性事件 1 EventBus.getDefault().postSticky(EventType type); 
 
进入postSticky:
1 2 3 4 5 6 7 8 9 public  void  postSticky (Object event)  {       synchronized  (stickyEvents) {                        stickyEvents.put(event.getClass(), event);        }                        post(event);    } 
 
在postSticky中将粘性事件放置在stickyEvents中,执行post事件,所以是先发送事件,
总结:在register中普通事件只是注册,而粘性事件多了一个步骤就是走了post的类似方法,在注册时会触发发布事件,这样在注册后就直接发布了。这就是粘性事件的原理。详看register源码