目錄
3.1.1 threadMode: 配置消息接收是在哪個線程
3.2.2 collectSubscribers收集訂閱類和訂閱的方法信息
3.3.2 查找訂閱方法findSubscriberMethods()
1. 架構圖
從官網的架構圖可以看出來,EventBus可以將發佈者和訂閱者解偶,這就是EventBus最大的方便之處。
2. 使用
請參考我的另外一篇文章:https://blog.csdn.net/fwt336/article/details/103133850
3. 源碼解析
3.1 @Subscribe註解
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface Subscribe {
ThreadMode threadMode() default ThreadMode.POSTING;
/**
* If true, delivers the most recent sticky event (posted with
* {@link EventBus#postSticky(Object)}) to this subscriber (if event available).
*/
boolean sticky() default false;
/** 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! */
int priority() default 0;
}
從Subscribe註解中的元註解可以看出來,我們的Subscribe是運行時註解,只能在運行時進行解析,也只能註冊Method方法。
裏面有三個參數可以進行配置:threadMode,sticky, priority。
3.1.1 threadMode: 配置消息接收是在哪個線程
有5種線程設置方式:
POSTING : 消息的接收與消息發送在同一個線程處理
MAIN : 消息在UI線程處理,但是如果發送線程是在UI線程,消息將會直接被調用處理,將阻塞調用線程。
MAIN_ORDERED : 消息在主線程處理,但是跟MAIN不一樣的是,消息將會加入到隊列中進行處理,不回堵塞調用線程。
BACKGROUND : 消息在後臺線程處理,如果發送線程不是UI線程,則將會直接在發送線程處理消息。如果發送線程是UI線程,那麼將使用一個後臺線程,按照事件順序處理。
ASYNC :消息將在單獨的線程中調用,如果消息處理很耗時,可以採用這種方法,最終是EventBus使用線程池來處理消息。
3.1.2 sticky : 粘性事件
默認爲false,如果設置爲true,其作用與粘性廣播的使用類似。也就是我們的粘性事件可以在事件註冊前發送,當註冊事件,並設置接收粘性事件後,將會接收到粘性事件。如果在註冊之前發送了兩個粘性事件,則只會接收到最後一個事件。
調用時,需用使用postSticky方法:
EventBus.getDefault().postSticky(new EventObject());
接收方法添加sticky = true即可,例如:
@Subscribe(threadMode = ThreadMode.Main, sticky = true)
stickyEventReceiver() {}
3.1.3 priority : 接收事件的優先級
在註冊時將會用到這個參數,根據優先級加入到訂閱者列表中。
3.2 註解解析
3.2.1 註解類上的元註解
先看看註解處理器上的註解修飾
@SupportedAnnotationTypes("org.greenrobot.eventbus.Subscribe")
@SupportedOptions(value = {"eventBusIndex", "verbose"})
public class EventBusAnnotationProcessor extends AbstractProcessor {}
SupportedAnnotationTypes : 指定處理器支持的處理類型
SupportedOptions : 用來表示所支持的附加選項
在運行apt命令行工具的時候,可以通過-A來傳遞額外的參數給註解處理器,如-Averbose=true。當通過 supportedOptions方法聲明瞭所能識別的附加選項之後,註解處理器就可以在運行時刻通過AnnotationProcessorEnvironment的getOptions方法獲取到選項的實際值。
public static final String OPTION_EVENT_BUS_INDEX = "eventBusIndex";
public static final String OPTION_VERBOSE = "verbose";
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment env) {
Messager messager = processingEnv.getMessager();
String index = processingEnv.getOptions().get(OPTION_EVENT_BUS_INDEX);
if (index == null) {
messager.printMessage(Diagnostic.Kind.ERROR, "No option " + OPTION_EVENT_BUS_INDEX +
" passed to annotation processor");
return false;
}
verbose = Boolean.parseBoolean(processingEnv.getOptions().get(OPTION_VERBOSE));
int lastPeriod = index.lastIndexOf('.');
String indexPackage = lastPeriod != -1 ? index.substring(0, lastPeriod) : null;
round++;
if (verbose) {
messager.printMessage(Diagnostic.Kind.NOTE, "Processing round " + round + ", new annotations: " +
!annotations.isEmpty() + ", processingOver: " + env.processingOver());
}
return true;
}
eventBusIndex選項值是註解器生成的一個類的路徑,是必須要傳遞的一個值,它是在build.gradle中進行傳遞的:
android {
defaultConfig {
javaCompileOptions {
annotationProcessorOptions {
arguments = [eventBusIndex: 'org.greenrobot.eventbusperf.MyEventBusIndex']
}
}
}
}
後面我們將會使用到這個類。
而verbose則是一個控制調試信息打印的變量,可傳可不傳。
3.2.2 collectSubscribers收集訂閱類和訂閱的方法信息
而我們的主要工作在下面三個方法上:
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment env) {
Messager messager = processingEnv.getMessager();
try {
// ...
collectSubscribers(annotations, env, messager); // 1.收集註解類和方法
checkForSubscribersToSkip(messager, indexPackage); // 2.過濾事件
if (!methodsByClass.isEmpty()) {
createInfoIndexFile(index); // 3.生成MyEventBusIndex類
} else {
messager.printMessage(Diagnostic.Kind.WARNING, "No @Subscribe annotations found");
}
// ...
} catch (RuntimeException e) {
}
return true;
}
看下collectSubscribers源碼:
private void collectSubscribers(Set<? extends TypeElement> annotations, RoundEnvironment env, Messager messager) {
for (TypeElement annotation : annotations) {
Set<? extends Element> elements = env.getElementsAnnotatedWith(annotation);
for (Element element : elements) {
if (element instanceof ExecutableElement) {
ExecutableElement method = (ExecutableElement) element;
if (checkHasNoErrors(method, messager)) {
TypeElement classElement = (TypeElement) method.getEnclosingElement();
methodsByClass.putElement(classElement, method);
}
} else {
messager.printMessage(Diagnostic.Kind.ERROR, "@Subscribe is only valid for methods", element);
}
}
}
}
它會遍歷每一個Subscriber標誌信息,將標註的類和標註方法對應起來,存儲到methodByClass裏,方便後面使用。
同時,它還會檢查方法是否被static修飾了,是不是被public修飾的,是否只有一個參數,也就是我們的事件參數只能是一個。
private boolean checkHasNoErrors(ExecutableElement element, Messager messager) {
if (element.getModifiers().contains(Modifier.STATIC)) { // 檢查是否有static修飾
messager.printMessage(Diagnostic.Kind.ERROR, "Subscriber method must not be static", element);
return false;
}
if (!element.getModifiers().contains(Modifier.PUBLIC)) { // 檢查是不是public修飾的
messager.printMessage(Diagnostic.Kind.ERROR, "Subscriber method must be public", element);
return false;
}
List<? extends VariableElement> parameters = ((ExecutableElement) element).getParameters();
if (parameters.size() != 1) { // 檢查參數是否有且只有一個
messager.printMessage(Diagnostic.Kind.ERROR, "Subscriber method must have exactly 1 parameter", element);
return false;
}
return true;
}
而我們收集到的數據methodsByClass將在checkForSubscribersToSkip方法和生成MyEventBusIndex時的writeIndexLines()方法中使用到。
checkForSubscribersToSkip流程:
private void checkForSubscribersToSkip(Messager messager, String myPackage) {
for (TypeElement skipCandidate : methodsByClass.keySet()) {
TypeElement subscriberClass = skipCandidate;
while (subscriberClass != null) {
if (!isVisible(myPackage, subscriberClass)) { // 判斷方法是否可見,public修飾或在同一個包內
boolean added = classesToSkip.add(skipCandidate);
break;
}
List<ExecutableElement> methods = methodsByClass.get(subscriberClass);
if (methods != null) {
for (ExecutableElement method : methods) {
String skipReason = null;
VariableElement param = method.getParameters().get(0);
TypeMirror typeMirror = getParamTypeMirror(param, messager);
if (!(typeMirror instanceof DeclaredType) ||
!(((DeclaredType) typeMirror).asElement() instanceof TypeElement)) {
skipReason = "event type cannot be processed";
}
if (skipReason == null) {
TypeElement eventTypeElement = (TypeElement) ((DeclaredType) typeMirror).asElement();
if (!isVisible(myPackage, eventTypeElement)) {
skipReason = "event type is not public";
}
}
if (skipReason != null) {
boolean added = classesToSkip.add(skipCandidate);
break;
}
}
}
// 遍歷父類中的方法
subscriberClass = getSuperclass(subscriberClass);
}
}
}
a.首先會遍歷所有標了Subscribe註解的類;
b.判斷類是否可見,即是否有public修飾,或是否與MyEventBusIndex.java在同一個包內,或沒有修飾符。不可見則放入classToSkip需要過濾的容器中;
private boolean isVisible(String myPackage, TypeElement typeElement) {
Set<Modifier> modifiers = typeElement.getModifiers();
boolean visible;
if (modifiers.contains(Modifier.PUBLIC)) {
visible = true;
} else if (modifiers.contains(Modifier.PRIVATE) || modifiers.contains(Modifier.PROTECTED)) {
visible = false;
} else {
String subscriberPackage = getPackageElement(typeElement).getQualifiedName().toString();
if (myPackage == null) {
visible = subscriberPackage.length() == 0;
} else {
visible = myPackage.equals(subscriberPackage);
}
}
return visible;
}
c.遍歷Subscribe標註的類對應的所有註解方法;
d.判斷Class是否是類或接口DeclaredType,不是則放入classToSkip需要過濾的容器中;
e.遍歷父類,重複b,c,d方法
3.2.3 生成MyEventBusIndex類
主要是看下writeIndexLines方法,其他生成的代碼都是固定的:
private void writeIndexLines(BufferedWriter writer, String myPackage) throws IOException {
for (TypeElement subscriberTypeElement : methodsByClass.keySet()) {
if (classesToSkip.contains(subscriberTypeElement)) {
continue;
}
String subscriberClass = getClassString(subscriberTypeElement, myPackage);
if (isVisible(myPackage, subscriberTypeElement)) {
writeLine(writer, 2,
"putIndex(new SimpleSubscriberInfo(" + subscriberClass + ".class,",
"true,", "new SubscriberMethodInfo[] {");
List<ExecutableElement> methods = methodsByClass.get(subscriberTypeElement);
writeCreateSubscriberMethods(writer, methods, "new SubscriberMethodInfo", myPackage);
writer.write(" }));\n\n");
} else {
writer.write(" // Subscriber not visible to index: " + subscriberClass + "\n");
}
}
}
也就是遍歷我們收集到的帶有@Subscribe註解的類,過濾出有效的類,再將我們的註冊類名和註解參數封裝起來,放入到SUBSCRIBER_INDEX這個map中,對外提供查找方法getSubscriberInfo()。
看下生成的這個類長什麼樣子:
package org.greenrobot.eventbusperf;
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(TestRunnerActivity.class, true, new SubscriberMethodInfo[] {
new SubscriberMethodInfo("onTestEvent", TestEvent.class, ThreadMode.MAIN),
}));
putIndex(new SimpleSubscriberInfo(TestActivity.class, true, new SubscriberMethodInfo[] {
new SubscriberMethodInfo("onDemoEvent", TestEvent.class, ThreadMode.MAIN_ORDERED, 0, true),
}));
}
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;
}
}
}
3.3 註冊流程解析
3.3.1 註冊流程
public void register(Object subscriber) {
Class<?> subscriberClass = subscriber.getClass();
List<SubscriberMethod> subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass);
synchronized (this) {
for (SubscriberMethod subscriberMethod : subscriberMethods) {
subscribe(subscriber, subscriberMethod);
}
}
}
大致流程是:通過註冊方法所在的類名,查找到所有註冊類的訂閱方法,然後在遍歷每個訂閱方法,將事件類型eventType跟訂閱器Subscription(內部封裝了訂閱類所需的所有參數)存入到subscriptionsByEventType中,而subscriptionsByEventType在進行消息分發查找時將會用到Subscription數據。
3.3.2 查找訂閱方法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;
}
}
從源碼可以發現查找方法名有兩種方式,一種時反射,另一種是通過獲取註解處理器生成的類MyEventBusIndex獲取,而默認ignoreGeneratedIndex是false。
反射查找所有方法則是通過獲取註冊類的所有方法,找到可見的且標註了@Subscribe註解的方法,然後封裝成SubscriberMethod類返回一個SubscriberMethod的list。
通過註解類查找定製類型的所有方法
註解處理器生成類的注入:
/** Adds an index generated by EventBus' annotation preprocessor. */
public EventBusBuilder addIndex(SubscriberInfoIndex index) {
if (subscriberInfoIndexes == null) {
subscriberInfoIndexes = new ArrayList<>();
}
subscriberInfoIndexes.add(index);
return this;
}
待用EventBusBuilder的addInex()方法後,這樣,我們的註解處理器的作用才真正達到了。
但是,當沒有配置註解器時,將強制使用反射方式進行處理。
那麼問題來了,你在使用EventBus時配置了EventBusIndex類嗎?
3.3.3 存儲訂閱類信息subscribe()
我們將subscribe()方法分爲三個部分來看。
a.存儲訂閱者信息
將訂閱事件和訂閱方法封裝到Subscription中,然後以列表的形式存儲在subscriptionsByEventType中,事件類型爲key。而訂閱事件發送的時候,也會從subscriptionsByEventType map中,將事件對應的subscriber訂閱器信息取出來,然後進行消息事件的反射。
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);
}
}
// ...處理事件優先級
List<Class<?>> subscribedEvents = typesBySubscriber.get(subscriber);
if (subscribedEvents == null) {
subscribedEvents = new ArrayList<>();
typesBySubscriber.put(subscriber, subscribedEvents);
}
subscribedEvents.add(eventType);
//...處理粘性事件
}
b. 處理消息事件優先級
private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) {
// ...
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;
}
}
// ...
}
每個方法插入列表的時候,將根據優先級插入,然後將列表保存在subscriptionsByEventType中。
c. 處理粘性消息
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);
}
}
}
eventInheritance默認爲true,所以會遍歷整個stickyEvents,然後將stickyEvents中的消息事件分發出去:
private void checkPostStickyEventToSubscription(Subscription newSubscription, Object stickyEvent) {
if (stickyEvent != null) {
postToSubscription(newSubscription, stickyEvent, isMainThread()); // 分發給對應的poster處理
}
}
3.3.4 取消訂閱
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--;
}
}
}
}
取消訂閱就比較簡單,只是將subscriptionsByEventType中對應的事件的註冊類移除即可。
3.4 消息發送和接收解析
3.4.1 postSticky粘性消息
public void postSticky(Object event) {
synchronized (stickyEvents) {
stickyEvents.put(event.getClass(), event);
}
// Should be posted after it is putted, in case the subscriber wants to remove immediately
post(event);
}
通過源碼我們可以發現,postSticky最終還是調用了post方法,只是會多一步將event加入stickyEvents中存儲起來,當註冊的時候會判斷是否有對應可能的粘性事件。
3.4.2 post普通消息
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。但是查了下沒有set方法,只有get,原來當沒有有效值時,內部創建了一個默認的PostingThreadState。
private final ThreadLocal<PostingThreadState> currentPostingThreadState = new ThreadLocal<PostingThreadState>() {
@Override
protected PostingThreadState initialValue() {
return new PostingThreadState();
}
};
當事件消息過來後,首先會通過ThreadLocal找到當前的線程PostingThreadState狀態,獲取到PostingThreadState中的隊列,然後加入到隊列中,如果此時線程正在分發消息,則退出,最後加入到消息將由正在分發消息的線程分發。
下面看下具體到消息分發:postSingleEvent(eventQueue.remove(0), postingState);
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));
}
}
}
接着會獲取到事件的類名,通過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 = 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;
}
最終通過事件類名從subscriptionsByEventType集合中找到對應的所有訂閱類,而我們在註冊的時候,將事件類名和訂閱類存入到類subscriptionsByEventType中。
找到所有的訂閱類subscriptions後,遍歷所有訂閱類,然後通過postToSubscription方法進行具體的消息分發處理。
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);
}
}
最終會通過初始化時的分發器,根據threadMode類型進行消息的處理。如果是posting線程則直接調用invokeSubscriber處理,如果是後臺線程或者異步線程,則都是調用EventBus的線程池進行處理消息隊列中的消息,而UI線程則是通過handler進行處理。
看下mainPoster的代碼就知道了,確實是通過new HandlerPoster處理的,而HandlerPoster繼承了Handler,並實現了Poster接口:
public interface MainThreadSupport {
boolean isMainThread();
Poster createPoster(EventBus eventBus);
class AndroidHandlerMainThreadSupport implements MainThreadSupport {
private final Looper looper;
public AndroidHandlerMainThreadSupport(Looper looper) {
this.looper = looper;
}
@Override
public boolean isMainThread() {
return looper == Looper.myLooper();
}
@Override
public Poster createPoster(EventBus eventBus) {
return new HandlerPoster(eventBus, looper, 10);
}
}
}
重點來了,最後所有消息處理都是通過反射實現的:
void invokeSubscriber(PendingPost pendingPost) {
Object event = pendingPost.event;
Subscription subscription = pendingPost.subscription;
PendingPost.releasePendingPost(pendingPost);
if (subscription.active) {
invokeSubscriber(subscription, event);
}
}
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);
}
}
終於看到了久違的invoke方法!
4. 總結
EventBus可以通過註解和反射兩種方式來獲取到訂閱者的相關信息,然後通過UI線程或內部的線程池處理髮送的消息事件,最終是通過反射實現訂閱者方法的調用,有訂閱者處理消息。