(1)eventbus的使用
為了方便分析EventBus的源碼逛揩,這里我們先整個demo出來辩稽,源碼如下:
public class MainActivity extends AppCompatActivity {
private TextView tvMessage;
private View btnSecond;
private Button btnRegister;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
EventBus.getDefault().register(this);
tvMessage = findViewById(R.id.tv_message);
btnSecond = findViewById(R.id.btn_second);
btnRegister = findViewById(R.id.tv_register);
btnRegister.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v) {
}
});
btnSecond.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(MainActivity.this,SecondActivity.class);
startActivity(intent);
}
});
loadData("http://www.baidu.com");
}
public void loadData(final String url){
new Thread(){
@Override
public void run() {
super.run();
String json = "message from MainActivity";
MessageEvent messageEvent = new MessageEvent("recode",json,"msg");
//在子線程當中發(fā)布類給主線程
// EventBus.getDefault().post(json);
EventBus.getDefault().post(messageEvent);
}
}.start();
}
// @Subscribe(threadMode = ThreadMode.MAIN,sticky = true)//MAIN代表主線程
@Subscribe(threadMode = ThreadMode.MAIN,sticky = false)
public void receiveMessage(MessageEvent messageEvent){//該方法名可更改,不影響任何東西各谚。
//在主線程中獲取子線程發(fā)送來的消息設(shè)置到TextView中
tvMessage.setText(messageEvent.getResult());
}
@Override
protected void onDestroy() {
super.onDestroy();
EventBus.getDefault().unregister(this);
}
}
(2)EventBus的register過程
- EventBus的初始化
public static EventBus getDefault() {
if (defaultInstance == null) {
synchronized (EventBus.class) {
if (defaultInstance == null) {
defaultInstance = new EventBus();
}
}
}
return defaultInstance;
}
可以看出:EventBus調(diào)用getDefault方法進行初始化憔四,并且使用了雙重否定的單例模式了赵。
- EventBus調(diào)用register方法進行事件訂閱
public void register(Object subscriber) {
Class<?> subscriberClass = subscriber.getClass();
List<SubscriberMethod> subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass);
synchronized (this) {
for (SubscriberMethod subscriberMethod : subscriberMethods) {
subscribe(subscriber, subscriberMethod);
}
}
}
- Subscriber:訂閱者對象柿汛,對應(yīng)demo中的MainActivity
- SubscriberMethod:是我們在Activity中定義的訂閱方法的一個描述類,里面保存了訂閱方法的信息妓羊,其實就是我們在Activity中定義的用@Subscriber注解修飾的receiveMessage(MessageEvent)方法。這里我截取了SubscriberMethod的成員變量信息净刮,如下所示:
public SubscriberMethod(Method method, Class<?> eventType, ThreadMode threadMode, int priority, boolean sticky) {
this.method = method;
this.threadMode = threadMode;
this.eventType = eventType;
this.priority = priority;
this.sticky = sticky;
}
method:方法名
ThreadMode:注解名稱
eventType:消息類型的字節(jié)碼對象,對應(yīng)demo中MessageEvent的class對象
priority:注解中priority屬性暑认,表示方法執(zhí)行的優(yōu)先級
- EventBus是如何找到subscriberMethod的集合的呢困介?
subscriberMethodFinder調(diào)用findSubscriberMethods(subscriberClass)方法找到了Subscriber對象(MainActivity)中所有訂閱方法信息的集合。
那么findSubscriberMethods是如何找到SubscriberMethod的呢蘸际?
我們接著往下看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;
}
}
- METHOD_CACHE:EventBus對Subscriber訂閱者的訂閱方法做的一個緩存,它是一個Map對象粮彤,key是Subscriber對象根穷,因為Subscriber對象可能有多個訂閱方法导坟,所以value是Subscriber對應(yīng)的訂閱方法的集合屿良。
可以看出EventBus先會從緩存中拿Subscriber對應(yīng)的SubscriberMethod的集合,如果緩存不為空乍迄,直接從緩存中獲取管引。
- ignoreGeneratedIndex:這個參數(shù)默認是為false,表示使用@Subscribe注解闯两,EventBus3.0版本后默認使用該注解來表示訂閱方法褥伴。而在EventBus3.0之前只能使用寫死的方法定義訂閱方法,這樣非常容易出錯漾狼。真正的獲取訂閱方法集合的方法其實是findUsingInfo(subscriberClass)方法重慢。
findUsingInfo的源碼如下所示:
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);
}
首先會執(zhí)行prepareFindState方法去獲取FindState,代碼如下:
private FindState prepareFindState() {
synchronized (FIND_STATE_POOL) {
for (int i = 0; i < POOL_SIZE; i++) {
FindState state = FIND_STATE_POOL[i];
if (state != null) {
FIND_STATE_POOL[i] = null;
return state;
}
}
}
return new FindState();
}
FIND_STATE_POOL:是一個最近使用且長度為4的FindState數(shù)組逊躁,目的是用來EventBus緩存FindState信息似踱,提升eventBus的運行效率的。
- FindState對象是什么稽煤?
static class FindState {
final List<SubscriberMethod> subscriberMethods = new ArrayList<>();
final Map<Class, Object> anyMethodByEventType = new HashMap<>();
final Map<String, Class> subscriberClassByMethodKey = new HashMap<>();
final StringBuilder methodKeyBuilder = new StringBuilder(128);
Class<?> subscriberClass;
Class<?> clazz;
boolean skipSuperClasses;
SubscriberInfo subscriberInfo;
}
開始我也有點懵逼核芽,各種類傻傻分不清,但是我們打個斷點就什么都明白了酵熙,其實FindState類就是一個保存將要查找的訂閱方法信息的類轧简。其主要成員變量如下:
subscriberMethods :SubScriber訂閱者(對應(yīng)demo中MainActivity)的所有訂閱方法的集合。
anyMethodByEventType :一個用來保存eventType(對應(yīng)demo中的EventMessage)和其對應(yīng)的method匾二。
subscriberClassByMethodKey :一個map對象哮独,key是一個訂閱方法名稱和EventType參數(shù)構(gòu)成的字符串,value為訂閱方法的class對象察藐。
subscriberClass和class:訂閱者類的class字節(jié)碼對象
如何獲取subscriber的訂閱方法皮璧?
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;
}
subscriberInfoIndexes 不為空會調(diào)用getSubscriberInfo方法獲取SubscriberInfo對象,SubscriberInfo對象包括了Subscriber和訂閱方法的信息分飞。后面我們發(fā)現(xiàn)SubscriberInfo是通過index.getSubscriberInfo()方法來得到的悴务。那么index指的是什么呢?
3.0版本中,EventBus提供了一個EventBusAnnotationProcessor注解處理器來在編譯期通過讀取@Subscribe()注解并解析,
處理其中所包含的信息,然后生成java類來保存所有訂閱者關(guān)于訂閱的信息,這樣就比在運行時使用反射來獲得這些訂閱者的
信息速度要快.我們可以參考EventBus項目里的EventBusPerformance這個例子,編譯后我們可以在build文件夾里找到這個類MyEventBusIndex 類譬猫,前面的index就屬于MyEventBusIndex對象類型
建議用git拉下EventBus的源碼惨寿,然后搜索EventBusAnnotationProcessor這個類邦泄,其源碼比較多,這里我們看看它的createInfoIndexFile方法裂垦,其源碼如下所示:
private void createInfoIndexFile(String index) {
BufferedWriter writer = null;
try {
JavaFileObject sourceFile = processingEnv.getFiler().createSourceFile(index);
int period = index.lastIndexOf('.');
String myPackage = period > 0 ? index.substring(0, period) : null;
String clazz = index.substring(period + 1);
writer = new BufferedWriter(sourceFile.openWriter());
if (myPackage != null) {
writer.write("package " + myPackage + ";\n\n");
}
writer.write("import org.greenrobot.eventbus.meta.SimpleSubscriberInfo;\n");
writer.write("import org.greenrobot.eventbus.meta.SubscriberMethodInfo;\n");
writer.write("import org.greenrobot.eventbus.meta.SubscriberInfo;\n");
writer.write("import org.greenrobot.eventbus.meta.SubscriberInfoIndex;\n\n");
writer.write("import org.greenrobot.eventbus.ThreadMode;\n\n");
writer.write("import java.util.HashMap;\n");
writer.write("import java.util.Map;\n\n");
writer.write("/** This class is generated by EventBus, do not edit. */\n");
writer.write("public class " + clazz + " implements SubscriberInfoIndex {\n");
writer.write(" private static final Map<Class<?>, SubscriberInfo> SUBSCRIBER_INDEX;\n\n");
writer.write(" static {\n");
writer.write(" SUBSCRIBER_INDEX = new HashMap<Class<?>, SubscriberInfo>();\n\n");
writeIndexLines(writer, myPackage);//把用了Subscriber注解的方法和方法所在的類信息拼湊起來
writer.write(" }\n\n");
writer.write(" private static void putIndex(SubscriberInfo info) {\n");
writer.write(" SUBSCRIBER_INDEX.put(info.getSubscriberClass(), info);\n");
writer.write(" }\n\n");
writer.write(" @Override\n");
writer.write(" public SubscriberInfo getSubscriberInfo(Class<?> subscriberClass) {\n");
writer.write(" SubscriberInfo info = SUBSCRIBER_INDEX.get(subscriberClass);\n");
writer.write(" if (info != null) {\n");
writer.write(" return info;\n");
writer.write(" } else {\n");
writer.write(" return null;\n");
writer.write(" }\n");
writer.write(" }\n");
writer.write("}\n");
} catch (IOException e) {
throw new RuntimeException("Could not write source for " + index, e);
} finally {
if (writer != null) {
try {
writer.close();
} catch (IOException e) {
//Silent
}
}
}
}
createInfoIndexFile方法其實就是在創(chuàng)建一個MyEventBusIndex.class文件顺囊,其中writeIndexLines方法是在把用了Subscriber注解的方法和方法所在的類信息拼湊起來,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");
}
}
}
下面再來看看EventBusAnnotationProcessor注解處理類生成的MyEventBusIndex這個類都長什么樣吧蕉拢,可以通過build EventBusPerformance這個model來生成它特碳。
public class MyEventBusIndex implements SubscriberInfoIndex {
private static final Map<Class<?>, SubscriberInfo> SUBSCRIBER_INDEX;
static {
SUBSCRIBER_INDEX = new HashMap<Class<?>, SubscriberInfo>();
putIndex(new SimpleSubscriberInfo(org.greenrobot.eventbusperf.testsubject.PerfTestEventBus.SubscribeClassEventBusMainOrdered.class,
true, new SubscriberMethodInfo[] {
new SubscriberMethodInfo("onEvent", TestEvent.class, ThreadMode.MAIN_ORDERED),
}));
putIndex(new SimpleSubscriberInfo(TestRunnerActivity.class, true, new SubscriberMethodInfo[] {
new SubscriberMethodInfo("onEventMainThread", TestFinishedEvent.class, ThreadMode.MAIN),
}));
putIndex(new SimpleSubscriberInfo(org.greenrobot.eventbusperf.testsubject.PerfTestEventBus.SubscribeClassEventBusBackground.class,
true, new SubscriberMethodInfo[] {
new SubscriberMethodInfo("onEventBackgroundThread", TestEvent.class, ThreadMode.BACKGROUND),
}));
putIndex(new SimpleSubscriberInfo(org.greenrobot.eventbusperf.testsubject.PerfTestEventBus.SubscribeClassEventBusMain.class,
true, new SubscriberMethodInfo[] {
new SubscriberMethodInfo("onEventMainThread", TestEvent.class, ThreadMode.MAIN),
}));
putIndex(new SimpleSubscriberInfo(org.greenrobot.eventbusperf.testsubject.SubscribeClassEventBusDefault.class,
true, new SubscriberMethodInfo[] {
new SubscriberMethodInfo("onEvent", TestEvent.class),
}));
putIndex(new SimpleSubscriberInfo(org.greenrobot.eventbusperf.testsubject.PerfTestEventBus.SubscriberClassEventBusAsync.class,
true, new SubscriberMethodInfo[] {
new SubscriberMethodInfo("onEventAsync", TestEvent.class, ThreadMode.ASYNC),
}));
}
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;
}
}
}
可以看出MyEventBusIndex這個類已經(jīng)把我們定義的訂閱方法信息全都用一個map保存起來了,key為Subscriber的字節(jié)碼類晕换,value為訂閱方法信息類午乓。后面也就不奇怪,我們可以通過迭代直接得到訂閱方法的信息了闸准。
如果EventBus沒有拿到MyEventBusIndex對象攜帶的訂閱方法信息的話益愈,那么將通過Subscriber對象手動解析帶有@subscribe注解的訂閱方法,當然這種方法效率太低了夷家,其實是一種容錯處理蒸其。這個解析過程便是通過findUsingReflectionInSingleClass實現(xiàn)的,如下所示:
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");
}
}
}
- 訂閱方法注冊過程
前面我們拿到了訂閱方法以及訂閱對象的信息后,并保持在SubscriberMethod集合中,后面會迭代這個集合潮酒,然后依次執(zhí)行subscribe方法。subscribe方法的源碼如下所示:
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()方法其實主要就干了這么幾件事:
對消息進行優(yōu)先級排序
緩存subscriber method的信息
subscriptionsByEventType這個Map對象的值就是用來緩存訂閱方法的信息的靠汁,其中key為EventType的class對象,value為Subscription對象的集合闽铐,而Subscription對象的成員變量就是訂閱者對象Subscriber以及訂閱方法SubscriberMethod蝶怔,這個map對象在后面發(fā)送消息時會用到,當要發(fā)送消息時兄墅,其實就是迭代這個對象添谊,然后利用發(fā)射執(zhí)行訂閱方法。如果有sticky消息察迟,直接發(fā)送。也可以得知sticky消息在注冊后是可以
執(zhí)行的耳高。
整個注冊的大致流程如下:
(2)發(fā)送消息和接收消息
由于sticky消息的發(fā)送最終也是執(zhí)行post方法扎瓶,這里只拿post方法來做分析,EventBus的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;
}
}
}
這個方法主要用來泌枪,判斷消息是否已經(jīng)發(fā)送概荷,方法執(zhí)行到底是否在主線程中,消息是否已經(jīng)取消碌燕,并且用EventType保存了如果符合要求误证,則程序繼續(xù)往下執(zhí)行postSingleEvent方法继薛,然后是各種判斷,接著會執(zhí)行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;
}
這個方法會拿出注冊時緩存訂閱方法的相關(guān)信息subscriptionsByEventType愈捅,并迭代這個Map對象遏考,取出訂閱方法的信息,并最終執(zhí)行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);
}
}
看到這里是不是有種似曾相識的感覺呢灌具?沒錯就是根據(jù)注解中threadMode的值,判斷方法在哪個線程中執(zhí)行譬巫,無論是在主線程還是子線程中執(zhí)行咖楣,最終都會invokeSubscriber方法,其實就是利用發(fā)射執(zhí)行Subscriber method芦昔,所以EventBus的post()方法執(zhí)行后诱贿,最終會執(zhí)行Subscriber method。
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);
}
}
POSTING:Subscriber和Subscriber Method在同一個線程中執(zhí)行
MAIN:Subscriber Method將在主線程中執(zhí)行咕缎,如果在主線程中直接執(zhí)行Subscriber Method珠十,如果在子線程中使用handler進行消息發(fā)送,并在主線程中執(zhí)行锨阿。
MAIN_ORDERED:主線程中按順序執(zhí)行Subscriber Method宵睦。
BACKGROUND:如果post方法發(fā)送消息在子線程中,那么直接執(zhí)行Subscriber method墅诡;如果post方法發(fā)送消息是在主線程中壳嚎,將會在子線程中執(zhí)行Subscriber method。
-
ASYNC:無論是在主線程還是子線程中發(fā)送消息末早,那么都講會子線程中執(zhí)行Subscriber method
(3) EventBus unRegister過程
unregister方法的源碼如下:
/** Unregisters the given subscriber from all event classes. */
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());
}
}
把之前Subscriber注冊時保存下來的訂閱方法信息刪除烟馅,然后執(zhí)行
unsubscribeByEventType方法,其代碼如下所示:
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--;
}
}
}
}
循環(huán)查找subScription對象并把它的active屬性改成false然磷,最后刪除subscription對象郑趁。
---------------end-----------------
如果文章對你有幫助的話,記得點一個贊哦姿搜。