/** Convenience singleton for apps using a process-wide EventBus instance. */publicstaticEventBusgetDefault(){EventBusinstance=defaultInstance;if(instance==null){synchronized(EventBus.class){instance=EventBus.defaultInstance;if(instance==null){instance=EventBus.defaultInstance=newEventBus();}}}returninstance;}
sequenceDiagram
EventBus->>SubscriberMethodFinder:findSubscriberMethodsfindUsingInfo
SubscriberMethodFinder->>SubscriberMethodFinder:findUsingInfo
SubscriberMethodFinder->>SubscriberMethodFinder:findUsingReflectionInSingleClass
SubscriberMethodFinder->>FindState:
Note over FindState,SubscriberMethodFinder:查找订阅类的Method并保存到FindStated中
SubscriberMethodFinder->>SubscriberMethodFinder:getMethodsAndRelease
SubscriberMethodFinder->>EventBus:返回List<SubscriberMethod>
Note over EventBus,SubscriberMethodFinder:遍历SubscriberMethod调用subscribe
EventBus->>EventBus:subscribe
Note right of EventBus:将Subscription添加到map中
public@interfaceSubscribe{ThreadModethreadMode()defaultThreadMode.POSTING;/** * If true, delivers the most recent sticky event (posted with * {@link EventBus#postSticky(Object)}) to this subscriber (if event available). */booleansticky()defaultfalse;/** 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! */intpriority()default0;}
publicclassSubscriberMethod{finalMethodmethod;//方法finalThreadModethreadMode;finalClass<?>eventType;finalintpriority;finalbooleansticky;/** Used for efficient comparison */StringmethodString;}
//查找订阅方法List<SubscriberMethod>findSubscriberMethods(Class<?>subscriberClass){//先从缓存中查找List<SubscriberMethod>subscriberMethods=METHOD_CACHE.get(subscriberClass);if(subscriberMethods!=null){returnsubscriberMethods;}if(ignoreGeneratedIndex){//默认是falsesubscriberMethods=findUsingReflection(subscriberClass);}else{subscriberMethods=findUsingInfo(subscriberClass);}if(subscriberMethods.isEmpty()){thrownewEventBusException("Subscriber "+subscriberClass+" and its super classes have no public methods with the @Subscribe annotation");}else{METHOD_CACHE.put(subscriberClass,subscriberMethods);returnsubscriberMethods;}}
privatevoidfindUsingReflectionInSingleClass(FindStatefindState){Method[]methods;try{// This is faster than getMethods, especially when subscribers are fat classes like Activitiesmethods=findState.clazz.getDeclaredMethods();}catch(Throwableth){// Workaround for java.lang.NoClassDefFoundError, see https://github.com/greenrobot/EventBus/issues/149try{methods=findState.clazz.getMethods();}catch(LinkageErrorerror){// super class of NoClassDefFoundError to be a bit more broad...Stringmsg="Could not inspect methods of "+findState.clazz.getName();if(ignoreGeneratedIndex){msg+=". Please consider using EventBus annotation processor to avoid reflection.";}else{msg+=". Please make this class visible to EventBus annotation processor to avoid reflection.";}thrownewEventBusException(msg,error);}findState.skipSuperClasses=true;}//遍历方法for(Methodmethod:methods){intmodifiers=method.getModifiers();if((modifiers&Modifier.PUBLIC)!=0&&(modifiers&MODIFIERS_IGNORE)==0){Class<?>[]parameterTypes=method.getParameterTypes();//判断参数个数是否是1如果不是1会抛出异常if(parameterTypes.length==1){//获取Subscribe注解SubscribesubscribeAnnotation=method.getAnnotation(Subscribe.class);//如果注解不为空if(subscribeAnnotation!=null){Class<?>eventType=parameterTypes[0];//获取事件类型if(findState.checkAdd(method,eventType)){ThreadModethreadMode=subscribeAnnotation.threadMode();//创建SubscriberMethod对象并添加到一个集合中findState.subscriberMethods.add(newSubscriberMethod(method,eventType,threadMode,subscribeAnnotation.priority(),subscribeAnnotation.sticky()));}}}elseif(strictMethodVerification&&method.isAnnotationPresent(Subscribe.class)){StringmethodName=method.getDeclaringClass().getName()+"."+method.getName();thrownewEventBusException("@Subscribe method "+methodName+"must have exactly 1 parameter but has "+parameterTypes.length);}}elseif(strictMethodVerification&&method.isAnnotationPresent(Subscribe.class)){StringmethodName=method.getDeclaringClass().getName()+"."+method.getName();thrownewEventBusException(methodName+" is a illegal @Subscribe method: must be public, non-static, and non-abstract");}}}
privatevoidsubscribe(Objectsubscriber,SubscriberMethodsubscriberMethod){Class<?>eventType=subscriberMethod.eventType;//事件类型SubscriptionnewSubscription=newSubscription(subscriber,subscriberMethod);//创建订阅对象CopyOnWriteArrayList<Subscription>subscriptions=subscriptionsByEventType.get(eventType);if(subscriptions==null){subscriptions=newCopyOnWriteArrayList<>();subscriptionsByEventType.put(eventType,subscriptions);}else{if(subscriptions.contains(newSubscription)){thrownewEventBusException("Subscriber "+subscriber.getClass()+" already registered to event "+eventType);}}intsize=subscriptions.size();for(inti=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=newArrayList<>();typesBySubscriber.put(subscriber,subscribedEvents);}subscribedEvents.add(eventType);//判断是否是粘性事件if(subscriberMethod.sticky){//如果是粘性时间,从stickyEvents获取事件if(eventInheritance){// Existing sticky events of all subclasses of eventType have to be considered.// Note: Iterating over all events may be inefficient with lots of sticky events,// thus data structure should be changed to allow a more efficient lookup// (e.g. an additional map storing sub classes of super classes: Class -> List<Class>).Set<Map.Entry<Class<?>,Object>>entries=stickyEvents.entrySet();for(Map.Entry<Class<?>,Object>entry:entries){Class<?>candidateEventType=entry.getKey();if(eventType.isAssignableFrom(candidateEventType)){ObjectstickyEvent=entry.getValue();checkPostStickyEventToSubscription(newSubscription,stickyEvent);}}}else{//如果是粘性事件 则从stickyEvents取出事件调用发送ObjectstickyEvent=stickyEvents.get(eventType);checkPostStickyEventToSubscription(newSubscription,stickyEvent);}}}
publicvoidpost(Objectevent){PostingThreadStatepostingState=currentPostingThreadState.get();List<Object>eventQueue=postingState.eventQueue;eventQueue.add(event);if(!postingState.isPosting){postingState.isMainThread=isMainThread();//判断是否是主线程postingState.isPosting=true;if(postingState.canceled){thrownewEventBusException("Internal error. Abort state was not reset");}try{while(!eventQueue.isEmpty()){postSingleEvent(eventQueue.remove(0),postingState);}}finally{postingState.isPosting=false;postingState.isMainThread=false;}}}
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}.
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.
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.
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.
privatevoidpostToSubscription(Subscriptionsubscription,Objectevent,booleanisMainThread){switch(subscription.subscriberMethod.threadMode){casePOSTING:invokeSubscriber(subscription,event);break;caseMAIN://判断当前发送的线程是否是主线程//如果是主线程直接调用Method的invoke方法,这样会阻塞UI线程if(isMainThread){invokeSubscriber(subscription,event);}else{//不是主线程则调用mainThreadPoster的enqueue方法mainThreadPoster.enqueue(subscription,event);}break;caseMAIN_ORDERED://无论是否是UI线程,都会排队发送if(mainThreadPoster!=null){mainThreadPoster.enqueue(subscription,event);}else{// temporary: technically not correct as poster not decoupled from subscriberinvokeSubscriber(subscription,event);}break;caseBACKGROUND://如果是UI线程会调用新的线程分发消息 如果不是UI线程直接调用if(isMainThread){backgroundPoster.enqueue(subscription,event);}else{invokeSubscriber(subscription,event);}break;caseASYNC://不管在什么线程都会开启一个新线程asyncPoster.enqueue(subscription,event);break;default:thrownewIllegalStateException("Unknown thread mode: "+subscription.subscriberMethod.threadMode);}}
publicclassHandlerPosterextendsHandlerimplementsPoster{//PendingPostQueue是链表实现的队列privatefinalPendingPostQueuequeue;privatefinalintmaxMillisInsideHandleMessage;privatefinalEventBuseventBus;privatebooleanhandlerActive;protectedHandlerPoster(EventBuseventBus,Looperlooper,intmaxMillisInsideHandleMessage){super(looper);this.eventBus=eventBus;this.maxMillisInsideHandleMessage=maxMillisInsideHandleMessage;queue=newPendingPostQueue();}publicvoidenqueue(Subscriptionsubscription,Objectevent){PendingPostpendingPost=PendingPost.obtainPendingPost(subscription,event);synchronized(this){//添加到队列中queue.enqueue(pendingPost);if(!handlerActive){handlerActive=true;//发送消息if(!sendMessage(obtainMessage())){thrownewEventBusException("Could not send handler message");}}}}@OverridepublicvoidhandleMessage(Messagemsg){booleanrescheduled=false;try{longstarted=SystemClock.uptimeMillis();while(true){//从队列中取出消息PendingPostpendingPost=queue.poll();if(pendingPost==null){synchronized(this){// Check again, this time in synchronizedpendingPost=queue.poll();if(pendingPost==null){handlerActive=false;return;}}}eventBus.invokeSubscriber(pendingPost);longtimeInMethod=SystemClock.uptimeMillis()-started;if(timeInMethod>=maxMillisInsideHandleMessage){if(!sendMessage(obtainMessage())){thrownewEventBusException("Could not send handler message");}rescheduled=true;return;}}}finally{handlerActive=rescheduled;}}}
publicvoidpostSticky(Objectevent){synchronized(stickyEvents){//添加到stickyEvents中stickyEvents.put(event.getClass(),event);}// Should be posted after it is putted, in case the subscriber wants to remove immediatelypost(event);}
publicsynchronizedvoidunregister(Objectsubscriber){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());}}