文章目錄
瞭解EventBus基本用法之前,要先了解一下它的三要素:
- Event:事件。可以是任意類型的對象
- Subscriber:事件訂閱者。3.0以後可隨意取名,添加@Subscribe註解並指定現場模型即可(默認POSTING)
- Publisher:事件發佈者。可在任意線程、位置發送事件,直接調用post方法
關於EventBus的4種線程模型:
- POSTING(默認):在同一個線程中發佈、接收事件。該模型中需儘量避免執行耗時操作,因爲其會阻塞事件傳遞,甚至ANR
- MAIN:在UI線程處理事件。處理事件太長會導致ANR
- BACKGROUND:若UI線程發佈,就在新線程處理;若在子線程發佈,就在當前線程處理。事件的處理函數中,禁止進行UI更新操作
- SYNC:無論在哪個線程發佈,都會在新線程中處理。事件的處理函數中,禁止進行UI更新操作
一、基本用法
自定義事件類:
/**
* 消息事件類
*/
public class MessageEvent {
private String message;
public MessageEvent(String message) {
this.message = message;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
在需要訂閱事件的地方,註冊事件:
// 註冊事件
EventBus.getDefault().register(this);
發送事件:
// 發送事件
EventBus.getDefault().post(new MessageEvent("發送事件"));
處理事件:
/**
* 處理事件
*/
@Subscribe(threadMode = ThreadMode.MAIN)
public void onMoonEvent(MessageEvent messageEvent){
// messageEvent.getMessage()就是接收的事件消息
}
取消事件訂閱:
// 取消訂閱
EventBus.getDefault().unregister(this);
順序就是先訂閱,再發送,然後才能接收。但是也有特例,這就是黏性事件。
1.1 黏性事件
EventBus還支持黏性事件,就是在發送事件之後,再訂閱,也能接收到該事件。粘性事件會保存在內存中,每次進入都會去內存中查找獲取最新的粘性事件,除非你手動解除註冊。
訂閱者處理黏性事件:
/**
* 處理黏性事件
*/
@Subscribe(threadMode = ThreadMode.MAIN,sticky = true)
public void onMoonEvent(MessageEvent messageEvent){
// messageEvent.getMessage()就是接收的事件消息
}
發送黏性事件:
// 發送黏性事件
EventBus.getDefault().postSticky(new MessageEvent("發送黏性事件"));
二、源碼分析
2.1 訂閱者註冊
2.1.1 EventBus.getDefault()
在使用EventBus時,要通過EventBus.getDefault()獲取EventBus實例。這個getDefault()方法用到了DCL模式:
// EventBus構造方法
public static EventBus getDefault() {
if (defaultInstance == null) {
synchronized (EventBus.class) {
if (defaultInstance == null) {
defaultInstance = new EventBus();
}
}
}
return defaultInstance;
}
這個單例模式中的DCL很重要,尤其是 synchronized 和 volatile 這兩個關鍵字的作用。
這裏我們看到通過 new EventBus() 來創建實例,看一下這個EventBus() 都做了什麼:
public EventBus() {
// DEFAULT_BUILDER就是默認的EventBusBuilder,用來構造EventBus
this(DEFAULT_BUILDER);
}
這個DEFAULT_BUILDER就是默認的EventBusBuilder,用來構造EventBus:
private static final EventBusBuilder DEFAULT_BUILDER = new EventBusBuilder();
this調用了EventBus的有參構造:
EventBus(EventBusBuilder builder) {
......
// 1 用來存儲事件對應的 訂閱者和訂閱者方法集合映射的封裝類
subscriptionsByEventType = new HashMap<>();
// 2 用來存儲註冊的訂閱者
typesBySubscriber = new HashMap<>();
// 3 用來存儲黏性事件
stickyEvents = new ConcurrentHashMap<>();
// 4 Android主線程處理事件
mainThreadSupport = builder.getMainThreadSupport();
mainThreadPoster = mainThreadSupport != null ? mainThreadSupport.createPoster(this) : null;
// Background事件發送者
backgroundPoster = new BackgroundPoster(this);
// 異步事件發送者
asyncPoster = new AsyncPoster(this);
indexCount = builder.subscriberInfoIndexes != null ? builder.subscriberInfoIndexes.size() : 0;
// 5 @Subscribe註解方法找尋器
subscriberMethodFinder = new SubscriberMethodFinder(builder.subscriberInfoIndexes,
builder.strictMethodVerification, builder.ignoreGeneratedIndex);
... 從builder取中一些列訂閱相關信息進行賦值
// 6 執行服務線程池
executorService = builder.executorService;
}
關於這個有參構造:
① 首先創建了一個subscriptionsByEventType對象(K爲Event類型,V爲Subscription鏈表)。Subscription是一個訂閱信息對象,它保存了**類型爲 Object 的 subscriber(註冊的對象,通常爲Activity對象)**和類型爲SubscriberMethod 的 subscriberMethod(被@Subscribe標註的訂閱方法)
② 創建類型爲 Map 的typesBySubscriber對象,K表示subscriber對象,V表示subscriber對象中所有的 Event 類型鏈表。作用就是判斷某個對象是否註冊過
③ 新建了一個類型爲ConcurrentHashMap的stickyEvents對象,專用於黏性事件處理的一個字段。K表示事件的Class對象,V表示當前的事件
④ 新建了3種類型的事件發送器:
- mainThreadPoster :UI線程事件發送器,通過mainThreadPoster.enqueue(subscription, event)方法可以將訂閱信息和對應的事件進行 “入隊” 操作。通過 handler 去發送消息,在 handleMessage 中執行。
- backgroundPoster:後臺事件發送器,通過enqueue() 將方法加入到後臺的一個隊列中,最後交給 線程池 執行。在Executor#execute()方法 上添加了 synchronized 並設立了控制標記 flag,保證任一時間有且僅有一個任務被線程池執行。
- asyncPoster:實現邏輯和backgroundPoster雷同,但asyncPoster則是異步運行的,可以同時接收多個任務。
⑤ 新建一個subscriberMethodFinder對象,這是從EventBus中抽離出的訂閱方法查詢的一個對象。
⑥ 從builder中取出一個默認的線程池對象,由Executors的newCachedThreadPool()方法創建,它是一個無數量上限的線程池(有就用,沒有就創建)。
很明顯EventBusBuilderEventBus的建造器,EventBus可以通過這個建造器,添加自定義的參數和安裝一個自定義的默認EventBus實例。這裏採用建造者模式,通過EventBusBuilder來對EventBus進行配置。這樣的設計,使得參數的配置更加靈活。
2.1.2 .register(this)
獲取到EventBus後,就將訂閱者註冊到EventBus中:
public void register(Object subscriber) {
Class<?> subscriberClass = subscriber.getClass();
// 1.藉助訂閱方法查找器,通過註解查找訂閱者的所有訂閱方法列表
List<SubscriberMethod> subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass);
synchronized (this) {
// 2.遍歷訂閱方法,訂閱註冊
for (SubscriberMethod subscriberMethod : subscriberMethods) {
subscribe(subscriber, subscriberMethod);
}
}
}
接下來查看SubscriberMethodFinder#findSubscriberMethods()方法是如何來查找訂閱者的訂閱方法的:
List<SubscriberMethod> findSubscriberMethods(Class<?> subscriberClass) {
// 1.如果緩存中有subscriberClass對象對應 的訂閱方法列表,則直接返回
List<SubscriberMethod> subscriberMethods = METHOD_CACHE.get(subscriberClass);
if (subscriberMethods != null) {
return subscriberMethods;
}
// 2.緩存中查不到,就判斷ignoreGeneratedIndex
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;
}
}
以上代碼中:
① 如果緩存中有subscriberClass對象對應 的訂閱方法列表,則直接返回
② ignoreGeneratedIndex字段很重要, 它用來判斷是否使用生成的 APT 代碼去優化尋找接收事件的過程。如果開啓,那麼將會通過 subscriberInfoIndexes 來快速得到接收事件方法的相關信息。如果我們沒有在項目中接入 EventBus 的 APT,那麼可以將 ignoreGeneratedIndex 字段設爲 false 以提高性能。ignoreGeneratedIndex 默認爲false,所以會執行findUsingInfo()方法,後面生成 subscriberMethods 成功的話會加入到緩存中,失敗的話會 拋出異常。這樣是爲了避免下次重新查找!
下面看一下執行的findUsingInfo()方法:
private List<SubscriberMethod> findUsingInfo(Class<?> subscriberClass) {
// 註釋1 創建一個新的 FindState 類
FindState findState = prepareFindState();
findState.initForSubscriber(subscriberClass);
while (findState.clazz != null) {
// 註釋2 獲取訂閱者信息
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 {
// 註釋3 將訂閱方法保存到findState中
findUsingReflectionInSingleClass(findState);
}
findState.moveToSuperclass();
}
// 註釋4
return getMethodsAndRelease(findState);
}
註釋1,通過prepareFindState方法創建了一個新的FindState 類:
private static final FindState[] FIND_STATE_POOL = new FindState[POOL_SIZE];
private FindState prepareFindState() {
// 1.從 FIND_STATE_POOL 即 FindState 池中取出可用的 FindState(這裏的POOL_SIZE爲4)
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;
}
}
}
// 2.如果沒有,就新建 一個新的 FindState 對象
return new FindState();
}
這個方法中一共就做了兩件事:
- ① 從FIND_STATE_POOL 即 FindState 池中取出可用的 FindState(這裏的POOL_SIZE爲4)
- ② 如果沒有,就創建一個新的 FindState對象
這個FindState 是SubscriberMethodFinder 的內部類,主要做一些初始化、回收對象的工作:
// FindState中間器,用於查找保存狀態
static class FindState {
......
// 初始化傳入訂閱類
void initForSubscriber(Class<?> subscriberClass) {
this.subscriberClass = clazz = subscriberClass;
skipSuperClasses = false;
subscriberInfo = null;
}
// 回收釋放,已備複用
void recycle() {...}
// 用來判斷FindState的anyMethodByEventType map是否已經添加過以當前eventType爲key的鍵值對,沒添加過則返回true
boolean checkAdd(Method method, Class<?> eventType) {...}
// 移動到父類Class
void moveToSuperclass() {...}
SubscriberMethodFinder的註釋2的getSubscriberInfo()方法獲取訂閱者信息:
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;
}
由於在上一步初始化的時候,findState的subscriberInfo和subscriberInfoIndexes 這兩個字段都爲null,於是直接在最後return null。
註釋3,findUsingReflectionInSingleClass()方法:
private void findUsingReflectionInSingleClass(FindState findState) {
Method[] methods;
try {
// 反射得到所有訂閱者的訂閱方法
methods = findState.clazz.getDeclaredMethods();
} catch (Throwable th) {
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");
}
}
}
這個方法做了一堆的事情:
- ① 利用反射來獲取訂閱者類中的所有聲明方法,在這些方法裏面尋找以 @Subscribe作爲註解的方法進行處理
- ② 在經過經過一輪檢查,看看 findState.subscriberMethods是否存在,如果沒有,將方法名,threadMode,優先級,是否爲 sticky 方法等信息封裝到 SubscriberMethod 對象中,最後添加到 subscriberMethods 列表中
註釋4,getMethodsAndRelease()方法:
private List<SubscriberMethod> getMethodsAndRelease(FindState findState) {
// 1.從findState中取出了保存的subscriberMethods
List<SubscriberMethod> subscriberMethods = new ArrayList<>(findState.subscriberMethods);
// 2.將findState裏的保存的所有對象進行回收
findState.recycle();
// 3.把findState存儲在 FindState 池中方便下一次使用,以提高性能
synchronized(FIND_STATE_POOL) {
for (int i = 0; i < POOL_SIZE; i++) {
if (FIND_STATE_POOL[i] == null) {
FIND_STATE_POOL[i] = findState;
break;
}
}
}
// 4.返回subscriberMethods
return subscriberMethods;
}
以上方法做了4件事:
① 從findState中取出了保存的subscriberMethods
② 將findState裏的保存的所有對象進行回收
③ 把findState存儲在 FindState 池中方便下一次使用,以提高性能
④ 返回subscriberMethods
最後,在EventBus的 register() 方法的最後會調用 subscribe 方法:
public void register(Object subscriber) {
Class<?> subscriberClass = subscriber.getClass();
List<SubscriberMethod> subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass);
synchronized (this) {
for (SubscriberMethod subscriberMethod : subscriberMethods) {
subscribe(subscriber, subscriberMethod);
}
}
}
// subscribe方法
private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) {
Class<?> eventType = subscriberMethod.eventType;
// 1.根據訂閱者Subscriber和訂閱方法SubscriberMethod,創建訂閱對象Subscription
Subscription newSubscription = new Subscription(subscriber, subscriberMethod);
// 2.根據事件類型EventType獲取訂閱對象集合Subscriptions,並將其保存到Map中
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();
// 3.按照訂閱方法的優先級插入到訂閱對象集合中,完成訂閱方法的註冊
for (int i = 0; i <= size; i++) {
if (i == size || subscriberMethod.priority > subscriptions.get(i).subscriberMethod.priority) {
subscriptions.add(i, newSubscription);
break;
}
}
// 4.獲取事件類型集合,將eventType添加其中,並將其按照subscriber存儲到Map中
List<Class<?>> subscribedEvents = typesBySubscriber.get(subscriber);
if (subscribedEvents == null) {
subscribedEvents = new ArrayList<>();
typesBySubscriber.put(subscriber, subscribedEvents);
}
subscribedEvents.add(eventType);
// 5.判斷是否是黏性事件
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);
}
}
}
這個方法做了四件事:
- ① 根據訂閱者Subscriber和訂閱方法SubscriberMethod,創建訂閱對象Subscription
- ② 根據事件類型eventType獲取訂閱對象集合subscriptions(null則重新創建),並將subscriptions按照eventType保存到Map中
- ③ 按照訂閱方法的優先級,插入到訂閱對象集合中,完成訂閱方法的註冊
- ④ 通過訂閱者subscriber獲取事件類型集合subscribedEvents(null則創建),並將eventType添加到subscribedEvents中,根據subscriber將subscribedEvents保存到Map中。
- ⑤ 判斷是否是黏性事件。如果是,會從stickyEvent事件保存隊列中取出該事件類型的事件,調用 checkPostStickyEventToSubscription() 方法來發送給當前訂閱者
2.2 post()
// 將給定事件發佈到事件總線
public void post(Object event) {
// 1.保存着事件隊列和線程狀態信息
PostingThreadState postingState = currentPostingThreadState.get();
// 獲取事件隊列,將當前事件插入事件隊列中
List<Object> eventQueue = postingState.eventQueue;
// 將傳入的event保存到eventQueue中
eventQueue.add(event);
// 2.將隊列中的時間依次交給postSingleEvent方法,並移除該事件
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;
}
}
}
這個currentPostingThreadState 是 ThreadLocal 類型的對象,裏面存儲了 PostingThreadState(PostingThreadState 中包含了一個 時間隊列eventQueue 和其他一些線程信息)。關於這個PostingThreadState:
private final ThreadLocal<PostingThreadState> currentPostingThreadState = new ThreadLocal<PostingThreadState>() {
@Override
protected PostingThreadState initialValue() {
return new PostingThreadState();
}
};
final static class PostingThreadState {
final List<Object> eventQueue = new ArrayList<>();
boolean isPosting;
boolean isMainThread;
Subscription subscription;
Object event;
boolean canceled;
}
總的來說,就是先從PostingThreadState 對象中取出事件隊列eventQueue,將當前事件插入到eventQueue中,再將eventQueue中的事件依次交給postSingleEvent方法處理,最後移除該事件。
接着會調用postSingleEvent() 方法:
private void postSingleEvent(Object event, PostingThreadState postingState) throws Error {
// 取出 Event 的 class 類型
Class<?> eventClass = event.getClass();
boolean subscriptionFound = false;
// 1. 是否向上查找事件的父類。默認true
if (eventInheritance) {
// 2.取出 Event 及其父類和接口的 class 列表
List<Class<?>> eventTypes = lookupAllEventTypes(eventClass);
int countTypes = eventTypes.size();
for (int h = 0; h < countTypes; h++) {
Class<?> clazz = eventTypes.get(h);
subscriptionFound |=
// 3
postSingleEventForEventType(event, postingState, clazz);
}
} else {
subscriptionFound = postSingleEventForEventType(event, postingState, eventClass);
}
if (!subscriptionFound) {
...
}
}
這個postSingleEvent() 方法:
- ① 判斷eventInheritance 標誌位,即是否向上查找事件的父類。默認爲true,false的話可以提升一些性能
- ② 調用lookupAllEventTypes() 方法,取出 Event 及其父類和接口的 class 列表。由於重複取會影響性能,所以做了一個 eventTypesCache 的緩存,避免了重複調用 getSuperclass() 方法
- ③ 調用postSingleEventForEventType()方法
關於這個postSingleEventForEventType()方法:
private boolean postSingleEventForEventType(Object event, PostingThreadState postingState, Class <?> eventClass) {
CopyOnWriteArrayList <Subscription> subscriptions;
// 同步取出訂閱對象集合
synchronized(this) {
subscriptions = subscriptionsByEventType.get(eventClass);
}
if (subscriptions != null && !subscriptions.isEmpty()) {
// 遍歷,將event對應的訂閱對象subscription傳遞給postingState
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;
}
這個postSingleEventForEventType()方法中,根據 Event 類型從 subscriptionsByEventType 中取出對應的 subscriptions對象,最後調用了 postToSubscription() 方法:
// 發佈到訂閱者,根據threadMode進行線程切換
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 {
// 如果是在子線程發送事件,則將事件入隊列,通過Handler切換到主線程執行處理事件
mainThreadPoster.enqueue(subscription, event);
}
break;
case MAIN_ORDERED://無論在哪個線程發送事件,都先將事件入隊列,然後通過 Handler 切換到主線程,依次處理事件。mainThreadPoster不會爲null
if (mainThreadPoster != null) {
mainThreadPoster.enqueue(subscription, event);
} else {
invokeSubscriber(subscription, event);
}
break;
case BACKGROUND: //若UI線程發佈,就在新線程處理;若在子線程發佈,就在當前線程處理
if (isMainThread) {
backgroundPoster.enqueue(subscription, event);
} else {
invokeSubscriber(subscription, event);
}
break;
case ASYNC: //無論在哪個線程發佈,都會在新線程中處理
asyncPoster.enqueue(subscription, event);
break;
default:
throw new IllegalStateException("Unknow thread mode: " + subscription.subscriberMethod.threadMode);
}
}
通過線程模型threadMode 來判斷在哪個線程中去執行方法,關於這幾種線程模型,上面已經介紹過了。
2.3 unregister()
public synchronized void unregister(Object subscriber) {
// 獲取訂閱者訂閱的所有事件
List<Class<?>> subscribedTypes = typesBySubscriber.get(subscriber);
if (subscribedTypes != null) {
// 遍歷訂閱類型集合,釋放之前緩存的當前類中的Subscription
for (Class<?> eventType : subscribedTypes) {
// 重點1
unsubscribeByEventType(subscriber, eventType);
}
// 重點2 刪除以subscriber爲key的鍵值對,更新typesBySubscriber
typesBySubscriber.remove(subscriber);
}
}
首先會獲取訂閱者訂閱的所有事件,遍歷它,並調用unsubscribeByEventType方法,釋放之前緩存的當前類中所有的訂閱信息Subscription
// 僅更新subscriptionsByEventType,而不更新typesBySubscriber
private void unsubscribeByEventType(Object subscriber, Class<?> eventType) {
// 得到當前參數類型對應的Subscription集合
List<Subscription> subscriptions = subscriptionsByEventType.get(eventType);
if (subscriptions != null) {
int size = subscriptions.size();
// 遍歷這個Subscription集合
for (int i = 0; i < size; i++) {
Subscription subscription = subscriptions.get(i);
// 如果當前subscription對象對應的註冊類對象 和 要取消註冊的註冊類對象相同,則刪除當前subscription對象
if (subscription.subscriber == subscriber) {
subscription.active = false;
subscriptions.remove(i);
i--;
size--;
}
}
}
}
隨後調用remove方法,移除了註冊對象和其對應的所有 Event 事件鏈表
2.4 postSticky()
public void postSticky(Object event) {
synchronized (stickyEvents) {
// 1.將黏性事件放到stickyEvents中
stickyEvents.put(event.getClass(), event);
}
// 2.調用post方法發送
post(event);
}
在register的最後提到了黏性:
if (subscriberMethod.sticky) {
Object stickyEvent = stickyEvents.get(eventType);
if (stickyEvent != null) {
postToSubscription(newSubscription, stickyEvent, isMainThread());
}
}
判斷當前事件是否是 sticky 事件,如果 是,則從 stickyEvents 中拿出該事件並執行 postToSubscription() 方法。