前言
EventBus是一種用於Android的發佈/訂閱事件總線。它有很多優點:簡化應用組件間的通信;解耦事件的發送者和接收者;避免複雜和容易出錯的依賴和生命週期的問題;很快,專門爲高性能優化過等等。
基礎知識
EventBus的基礎知識和使用詳解可以閱讀這篇文章:EventBus使用詳解
源碼分析
EventBus源碼分析主要分爲兩個過程:
- 訂閱事件
- 發佈事件
在分析訂閱事件之前,我們先來分析一下與訂閱事件相關的訂閱者索引。
訂閱者索引
默認情況下,EventBus使用Java反射來查找訂閱者信息。訂閱者索引是EventBus 3的一個新特性。它可以加速查找訂閱者信息的過程,是一個可選的優化。訂閱者索引的原理是:使用EventBus的註解處理器在應用構建期間創建訂閱者索引類,該類已經包含了所有的訂閱者信息。EventBus官方推薦在Android中使用訂閱者索引以獲得最佳的性能。
要開啓訂閱者索引的生成,你需要在構建腳本中使用annotationProcessor屬性將EventBus的註解處理器添加到應用的構建中,還要設置一個eventBusIndex參數來指定要生成的訂閱者索引的完全限定類名。
首先,修改模塊下的build.gradle構建腳本。如下所示:
android {
defaultConfig {
...
javaCompileOptions {
annotationProcessorOptions {
arguments = [eventBusIndex: 'com.github.cyc.eventbus.subscriberindexdemo.MyEventBusIndex']
}
}
}
...
}
dependencies {
...
compile 'org.greenrobot:eventbus:3.1.1'
annotationProcessor 'org.greenrobot:eventbus-annotation-processor:3.1.1'
}
然後,build一下工程。EventBus註解處理器將爲你生成一個訂閱者索引類。示例代碼如下所示:
package com.github.cyc.eventbus.subscriberindexdemo;
import org.greenrobot.eventbus.meta.SimpleSubscriberInfo;
import org.greenrobot.eventbus.meta.SubscriberMethodInfo;
import org.greenrobot.eventbus.meta.SubscriberInfo;
import org.greenrobot.eventbus.meta.SubscriberInfoIndex;
import org.greenrobot.eventbus.ThreadMode;
import java.util.HashMap;
import java.util.Map;
/** This class is generated by EventBus, do not edit. */
public class MyEventBusIndex implements SubscriberInfoIndex {
private static final Map<Class<?>, SubscriberInfo> SUBSCRIBER_INDEX;
static {
SUBSCRIBER_INDEX = new HashMap<Class<?>, SubscriberInfo>();
putIndex(new SimpleSubscriberInfo(MainActivity.class, true, new SubscriberMethodInfo[] {
new SubscriberMethodInfo("onMessageEvent", MessageEvent.class, ThreadMode.MAIN),
}));
}
private static void putIndex(SubscriberInfo info) {
SUBSCRIBER_INDEX.put(info.getSubscriberClass(), info);
}
@Override
public SubscriberInfo getSubscriberInfo(Class<?> subscriberClass) {
SubscriberInfo info = SUBSCRIBER_INDEX.get(subscriberClass);
if (info != null) {
return info;
} else {
return null;
}
}
}
可以看到,所有的訂閱者信息都先被保存在SUBSCRIBER_INDEX靜態成員變量中。後面查找訂閱者信息時,EventBus就可以直接調用getSubscriberInfo()方法來獲取該訂閱者的信息了。
最後,在應用自定義的Application類的onCreate()方法中將訂閱者索引添加到EventBus中,並將該EventBus設置成默認的EventBus。示例代碼如下所示:
public class MyApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
// 配置EventBus
EventBus.builder().addIndex(new MyEventBusIndex()).installDefaultEventBus();
}
}
我們來看builder()、addIndex()和installDefaultEventBus()方法的代碼:
public class EventBus {
static volatile EventBus defaultInstance;
...
public static EventBusBuilder builder() {
return new EventBusBuilder();
}
}
public class EventBusBuilder {
...
List<SubscriberInfoIndex> subscriberInfoIndexes;
public EventBusBuilder addIndex(SubscriberInfoIndex index) {
if (subscriberInfoIndexes == null) {
subscriberInfoIndexes = new ArrayList<>();
}
subscriberInfoIndexes.add(index);
return this;
}
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;
}
}
public EventBus build() {
return new EventBus(this);
}
}
builder()靜態方法新建了一個EventBusBuilder對象。addIndex()方法將生成的訂閱者索引添加到EventBusBuilder對象的subscriberInfoIndexes成員變量中。installDefaultEventBus()方法調用了build()方法新建了一個EventBus對象,並將該對象賦值給EventBus的defaultInstance靜態成員變量。這樣,後面調用EventBus.getDefault()靜態方法獲取到的就是該EventBus對象了。我們接着來看EventBus.getDefault()靜態方法的代碼:
public class EventBus {
static volatile EventBus defaultInstance;
private static final EventBusBuilder DEFAULT_BUILDER = new EventBusBuilder();
private final Map<Class<?>, CopyOnWriteArrayList<Subscription>> subscriptionsByEventType;
private final Map<Object, List<Class<?>>> typesBySubscriber;
private final Map<Class<?>, Object> stickyEvents;
private final Poster mainThreadPoster;
private final BackgroundPoster backgroundPoster;
private final AsyncPoster asyncPoster;
private final SubscriberMethodFinder subscriberMethodFinder;
...
public static EventBus getDefault() {
if (defaultInstance == null) {
synchronized (EventBus.class) {
if (defaultInstance == null) {
defaultInstance = new EventBus();
}
}
}
return defaultInstance;
}
public EventBus() {
this(DEFAULT_BUILDER);
}
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;
}
}
getDefault()靜態方法使用了單例模式,保證只有一個默認的EventBus實例。EventBus實例的創建使用了建造者模式。無論是調用了installDefaultEventBus()方法,還是隻調用了getDefault()靜態方法,最終都調用了EventBus(EventBusBuilder builder)構造方法來創建EventBus實例。EventBus()構造方法主要是初始化了一些數據結構和複製了EventBusBuilder對象的配置值:
- subscriptionsByEventType成員變量以事件類型的Class對象爲鍵,用於保存訂閱了該事件類型的所有的訂閱者信息。
- typesBySubscriber成員變量以訂閱者對象爲鍵,用於保存該訂閱者訂閱的所有的事件類型。
- stickyEvents成員變量以事件類型的Class對象爲鍵,用於保存該事件類型最近一次發佈的粘性事件。
- mainThreadPoster成員變量用於ThreadMode.MAIN和ThreadMode.MAIN_ORDERED線程模式下事件的傳遞。
- backgroundPoster成員變量用於ThreadMode.BACKGROUND線程模式下事件的傳遞。
- asyncPoster成員變量用於ThreadMode.ASYNC線程模式下事件的傳遞。
- subscriberMethodFinder成員變量用於查找訂閱者方法。它保存了EventBusBuilder對象的subscriberInfoIndexes成員變量,也就是訂閱者索引。
訂閱事件
訂閱事件主要分爲兩個過程:
- 註冊訂閱者
- 註銷訂閱者
調用register()方法可以註冊一個訂閱者。我們先來看register()方法的代碼:
public class EventBus {
public void register(Object subscriber) {
Class<?> subscriberClass = subscriber.getClass();
List<SubscriberMethod> subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass);
synchronized (this) {
for (SubscriberMethod subscriberMethod : subscriberMethods) {
subscribe(subscriber, subscriberMethod);
}
}
}
...
}
register()方法先調用了subscriberMethodFinder成員變量的findSubscriberMethods()方法來查找該訂閱者的訂閱者方法,然後才調用subscribe()方法開始註冊訂閱者。所以,我們先來分析一下查找訂閱者方法的過程。
查找訂閱者方法
我們來看findSubscriberMethods()方法的代碼:
class SubscriberMethodFinder {
...
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;
}
}
private List<SubscriberMethod> findUsingReflection(Class<?> subscriberClass) {
FindState findState = prepareFindState();
findState.initForSubscriber(subscriberClass);
while (findState.clazz != null) {
findUsingReflectionInSingleClass(findState);
findState.moveToSuperclass();
}
return getMethodsAndRelease(findState);
}
}
findSubscriberMethods()方法先從METHOD_CACHE緩存中獲取訂閱者方法。如果獲取到了訂閱者方法,那麼直接返回。反之,開始查找訂閱者的訂閱者方法。ignoreGeneratedIndex成員變量表示是否忽略生成的訂閱者索引,它來自EventBusBuilder對象的ignoreGeneratedIndex成員變量,默認值爲false,表示不忽略。因此,默認情況下,將調用findUsingInfo()方法來查找訂閱者方法。如果用戶沒有生成或者添加訂閱者索引的話,那麼findUsingInfo()方法將與findUsingReflection()方法一樣最終調用findUsingReflectionInSingleClass()方法使用Java反射來查找訂閱者方法。如果沒有查找到訂閱者方法,那麼將拋出EventBusException異常。反之,先更新METHOD_CACHE緩存,然後再返回。我們接着來看findUsingInfo()方法的代碼:
class SubscriberMethodFinder {
private List<SubscriberMethod> findUsingInfo(Class<?> subscriberClass) {
FindState findState = prepareFindState();
findState.initForSubscriber(subscriberClass);
while (findState.clazz != null) {
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.add(subscriberMethod);
}
}
} else {
findUsingReflectionInSingleClass(findState);
}
findState.moveToSuperclass();
}
return getMethodsAndRelease(findState);
}
private SubscriberInfo getSubscriberInfo(FindState findState) {
if (findState.subscriberInfo != null && findState.subscriberInfo.getSuperSubscriberInfo() != null) {
SubscriberInfo superclassInfo = findState.subscriberInfo.getSuperSubscriberInfo();
if (findState.clazz == superclassInfo.getSubscriberClass()) {
return superclassInfo;
}
}
if (subscriberInfoIndexes != null) {
for (SubscriberInfoIndex index : subscriberInfoIndexes) {
SubscriberInfo info = index.getSubscriberInfo(findState.clazz);
if (info != null) {
return info;
}
}
}
return null;
}
...
}
findUsingInfo()方法使用了while循環,不僅查找了訂閱者的訂閱者方法,而且查找了訂閱者父類的訂閱者方法。findUsingInfo()方法先調用了getSubscriberInfo()方法來獲取訂閱者信息。如果生成並添加了訂閱者索引,即subscriberInfoIndexes成員變量不爲null,那麼getSubscriberInfo()方法將遍歷subscriberInfoIndexes成員變量來查找訂閱者信息。如果獲取到了訂閱者信息,那麼將訂閱者信息裏的訂閱者方法保存起來。反之,調用findUsingReflectionInSingleClass()方法來查找訂閱者方法。我們接着來看findUsingReflectionInSingleClass()方法的代碼:
class SubscriberMethodFinder {
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();
if ((modifiers & Modifier.PUBLIC) != 0 && (modifiers & MODIFIERS_IGNORE) == 0) {
Class<?>[] parameterTypes = method.getParameterTypes();
if (parameterTypes.length == 1) {
Subscribe subscribeAnnotation = method.getAnnotation(Subscribe.class);
if (subscribeAnnotation != null) {
Class<?> eventType = parameterTypes[0];
if (findState.checkAdd(method, eventType)) {
ThreadMode threadMode = subscribeAnnotation.threadMode();
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");
}
}
}
...
}
findUsingReflectionInSingleClass()方法使用了Java反射來查找訂閱者方法。只有那些同時滿足public訪問權限、非static方法、非abstract方法、有且只有一個參數和使用了@Subscribe註解的方法才被當做是合法的訂閱者方法。
註冊訂閱者
register()方法在查找到訂閱者所有的訂閱者方法之後,遍歷訂閱者方法爲每個訂閱者方法調用了subscribe()方法。我們接着來看subscribe()方法的代碼:
public class EventBus {
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);
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<Class>).
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);
}
}
}
...
}
首先,subscribe()方法創建了一個包含了該訂閱者方法和對應訂閱者的Subscription對象,並根據訂閱者方法的事件傳遞優先級將該Subscription對象添加到對應事件類型的Subscription列表中。然後,將該訂閱者方法對應的事件類型添加到對應訂閱者的訂閱事件類型列表中。最後,如果是訂閱了粘性事件的訂閱者方法,那麼會先獲取對應事件類型的粘性事件並最終調用postToSubscription()方法將該粘性事件發送給訂閱者。
註銷訂閱者
調用unregister()方法可以註銷一個訂閱者。我們接着來看unregister()方法的代碼:
public class EventBus {
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());
}
}
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--;
}
}
}
}
...
}
首先,unregister()方法獲取了該訂閱者訂閱的所有的事件類型列表。然後,遍歷事件類型列表對每個事件類型調用unsubscribeByEventType()方法。unsubscribeByEventType()方法先獲取訂閱了該事件類型的所有的Subscription列表,然後從列表中刪除了與該訂閱者相關的Subscription對象。最後,從typesBySubscriber成員變量中刪除了該訂閱者訂閱的所有的事件類型列表。
發佈事件
調用post()方法可以發佈一個事件。我們接着來看post()方法的代碼:
public class EventBus {
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;
}
}
}
...
}
post()方法先將事件添加到當前線程的PostingThreadState對象的事件隊列的末尾。最終調用了postSingleEvent()方法將事件發佈出去。我們接着來看postSingleEvent()方法的代碼:
public class EventBus {
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));
}
}
}
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;
}
...
}
eventInheritance成員變量表示是否需要考慮事件的繼承,即是否要發佈對應事件類型的父類型的事件。它來自EventBusBuilder對象的eventInheritance成員變量,默認值爲true,表示需要考慮事件的繼承。因此,默認情況下,postSingleEvent()方法不僅調用了postSingleEventForEventType()方法發佈了對應事件類型的事件,而且發佈了對應事件類型的父類型的事件。postSingleEventForEventType()方法先獲取訂閱了該事件類型的所有的Subscription列表。然後遍歷Subscription列表對每個Subscription對象調用了postToSubscription()方法將事件發佈出去。我們接着來看postToSubscription()方法的代碼:
public class EventBus {
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 {
// 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);
}
}
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);
}
}
...
}
postToSubscription()方法針對每一種線程模式使用了對應的發佈事件策略:
- ThreadMode.POSTING。在當前發佈事件的線程中直接調用訂閱者方法。
- ThreadMode.MAIN。如果當前線程就是主線程,那麼直接調用訂閱者方法。反之,先進入隊列,後面將在主線程的Handler中調用訂閱者方法。
- ThreadMode.MAIN_ORDERED。直接進入隊列,後面將在主線程的Handler中調用訂閱者方法。
- ThreadMode.BACKGROUND。如果當前線程不是主線程,那麼直接調用訂閱者方法。反之,先進入隊列,後面將在線程池的工作線程中調用訂閱者方法。
- ThreadMode.ASYNC。直接進入隊列,後面將在線程池的工作線程中調用訂閱者方法。
以上調用訂閱者方法都是通過調用invokeSubscriber()方法以Java反射的方式調用的。
總結
EventBus是一種用於Android的發佈/訂閱事件總線。使用EventBus可以簡化應用組件間的通信,可以解耦事件的發送者和接收者。