本文將從EventBus 創(chuàng)建 - > 注冊--->發(fā)送消息--->解除注冊 幾個方面來讀一下EventBus 3.0+ 的源碼。
EventBus 簡單訂閱 (例如,在MainActivity.class 檬嘀,注冊String.class 類型的事件) 代碼如下:
//MainActivity.class
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//....
EventBus.getDefault().register(this);
}
//類中的伐弹,訂閱方法, 事件類型為String
@Subscribe(threadMode = ThreadMode.MAIN, priority = 100, sticky = false)
public void onStringEvent(String eventString) {
}
上面代碼在別的地方發(fā)送 事件類型為 String.class
則會調(diào)用到 MainActivity#onStringEvent
方法亲雪。
一、EventBus 創(chuàng)建
EventBus.getDefault(); // 返回的是EventBus對象
這里的 EventBus.getDefault()
其實是拿到的EventBus對象疚膊,其中涉及到了一個 線程安全的單利模式义辕,代碼如下(參數(shù)解釋標注在了注釋中):
EventBus.java
static volatile EventBus defaultInstance;
//線程安全的單例模式
public static EventBus getDefault() {
if (defaultInstance == null) {
synchronized (EventBus.class) {//加鎖
if (defaultInstance == null) {
defaultInstance = new EventBus(); //如果不存在,則去創(chuàng)建
}
}
}
return defaultInstance;
}
如果不存在酿联,就走下面的創(chuàng)建方法:
EventBus.java
//創(chuàng)建過程
EventBus(EventBusBuilder builder) {
//private final Map<Class<?>, CopyOnWriteArrayList<Subscription>> subscriptionsByEventType;
//key:訂閱的事件,value:訂閱這個事件的所有訂閱者集合
subscriptionsByEventType = new HashMap<>();
//private final Map<Object, List<Class<?>>> typesBySubscriber;
//key:訂閱者對象,value:這個訂閱者訂閱的事件集合
typesBySubscriber = new HashMap<>();
//粘性事件 key:粘性事件的class對象, value:事件對象
//private final Map<Class<?>, Object> stickyEvents;
stickyEvents = new ConcurrentHashMap<>();
//ui線程的 Handler
mainThreadPoster = new HandlerPoster(this, Looper.getMainLooper(), 10);
//Background 處理
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;
}
二终息、EventBus注冊
1,使用(下面的this贞让,就是上面例子中的 MainActivity.class
)
//最常用的EventBus注冊
EventBus.getDefault().register(this);
1.1 主要看 EventBus.java ->register()
EventBus.java
/**
* 大概翻譯一下周崭,該方法上的注釋的意思。
* 1喳张,記得調(diào)用 {@link #unregister(Object)} 進行注冊解除
* 2续镇,訂閱者,需要有一個包含 {@link Subscribe} 注解的方法销部。
*/
public void register(Object subscriber) {
//1摸航,拿到訂閱的class 上面例子中的 `MainActivity.class`
Class<?> subscriberClass = subscriber.getClass();
//2制跟,通過subscriberMethodFinder來找到訂閱者訂閱了哪些事件.返回一個SubscriberMethod對象的List,SubscriberMethod
//里包含了這個方法的Method對象,以及將來響應訂閱是在哪個線程的ThreadMode,以及訂閱的事件類型eventType,以及訂閱的優(yōu)
//先級priority,以及是否接收粘性sticky事件的boolean值.
List<SubscriberMethod> subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass);
synchronized (this) {
//3,從步驟2得到的集合酱虎,說明一個類中可能有很多個訂閱方法雨膨,在下面通過foreach依次 訂閱。
for (SubscriberMethod subscriberMethod : subscriberMethods) {
//
subscribe(subscriber, subscriberMethod);
}
}
}
1.2 跟到:SubscriberMethodFinder.java --> findSubscriberMethods()
方法中读串,可以理解為:尋找到 類中所有帶@Subscribe
注解的方法
/**
* METHOD_CACHE 本質是一個 key = class 聊记,value = List<SubscriberMethod> 的線程安全的map集合。
*/
private static final Map<Class<?>, List<SubscriberMethod>> METHOD_CACHE = new ConcurrentHashMap<>();
//-------------------------------------------------
List<SubscriberMethod> findSubscriberMethods(Class<?> subscriberClass) {
//METHOD_CACHE :緩存恢暖,先從緩存中獲取
List<SubscriberMethod> subscriberMethods = METHOD_CACHE.get(subscriberClass);
if (subscriberMethods != null) {
//如果不為null排监,說明之前緩存的Map集合中有,直接return杰捂,返回
return subscriberMethods;
}
//ignoreGeneratedIndex 默認是 false
if (ignoreGeneratedIndex) {
// 使用反射方式獲取(反射繼續(xù)跟會到這個方法中:findUsingReflectionInSingleClass(findState);舆床,在這個方法中,通過@Subscriber注解嫁佳,找到相應的方法)
subscriberMethods = findUsingReflection(subscriberClass);
} else {
// 使用SubscriberIndex方式獲取
subscriberMethods = findUsingInfo(subscriberClass);
}
if (subscriberMethods.isEmpty()) {
//在這里也可以看到挨队,如果沒有一個 聲明為 public + 含有 @Subscribe 的方法,就會拋異常蒿往!
throw new EventBusException("Subscriber " + subscriberClass
+ " and its super classes have no public methods with the @Subscribe annotation");
} else {
//在這里瞒瘸,將傳入的class 作為key,存到 subscriberMethods 中熄浓。
METHOD_CACHE.put(subscriberClass, subscriberMethods);
return subscriberMethods;
}
}
由于ignoreGeneratedIndex
默認是 false,則進入 else 中分析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);
}
-
getSubscriberInfo(findState);
該方法默認為null省撑,因為赌蔑,在findState.initForSubscriber(subscriberClass)
初始化的時候,findState.subscriberInfo = null
第一個 if 判斷不會走竟秫。subscriberInfoIndexes
涉及到了 apt 娃惯,默認也是 null (可以進入EventBusBuilder # addIndex()
進行驗證)
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;
}
1.3 繼續(xù)看 findUsingReflectionInSingleClass
, 找到 添加注解方法的核心(關鍵代碼在注解中進行解釋)
// SubscriberMethodFinder.java
private void findUsingReflectionInSingleClass(FindState findState) {
Method[] methods;
try {
// 這里的 clazz 也就是平常我們寫的類肥败,如:MainActivity等等
//反射趾浅,得到 類 方法的數(shù)組
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;
}
//遍歷方法,找到包含注解的方法 (上面例子中 `onStringEvent(String eventString)` 方法)
for (Method method : methods) {
int modifiers = method.getModifiers();
//判斷修飾符馒稍,是不是 public
if ((modifiers & Modifier.PUBLIC) != 0 && (modifiers & MODIFIERS_IGNORE) == 0) {
Class<?>[] parameterTypes = method.getParameterTypes();
//保證必須只有一個參數(shù)皿哨,其實就是注解方法中只能有一個事件(上面例子中的 String.class 類型)
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");
}
}
}
總結:
上面步驟主要做的是,找到訂閱class中的訂閱方法 SubscriberMethod
纽谒,并保存证膨。
繼續(xù)分析 EventBus.java ->register() --> subscribe()
訂閱方法
//這里的 subscriber(訂閱者) 也就是 `MainActivity.class` ,
private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) {
//獲取方法參數(shù)事件的 class 鼓黔,例如上面例子的:`String.class`
Class<?> eventType = subscriberMethod.eventType;
//創(chuàng)建Subscription對象
Subscription newSubscription = new Subscription(subscriber, subscriberMethod);
//從subscriptionsByEventType里檢查是否已經(jīng)添加過該Subscription,如果添加過就拋出異常
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);
}
}
//根據(jù)優(yōu)先級priority來添加Subscription對象央勒,ps:優(yōu)先級越大越靠前
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;
}
}
//將訂閱者對象以及訂閱的事件保存到typesBySubscriber里.
List<Class<?>> subscribedEvents = typesBySubscriber.get(subscriber);
if (subscribedEvents == null) {
subscribedEvents = new ArrayList<>();
typesBySubscriber.put(subscriber, subscribedEvents);
}
subscribedEvents.add(eventType);
//如果接收sticky事件,立即分發(fā)sticky事件
if (subscriberMethod.sticky) {
//eventInheritance 表示是否分發(fā)訂閱了響應事件類父類事件的方法
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);
}
}
}
Map<Class<?>, CopyOnWriteArrayList<Subscription>> subscriptionsByEventType;
:key:代表的是事件類型不见,如String.class
;value:線程安全的List,保存的是一組訂閱該(String.class)事件的訂閱崔步。通俗來說就是:String.class
事件可能被 A B C...等等類訂閱稳吮,這個List就是訂閱String.class
所有集合。
完成以上過程就完成了注冊過程井濒。黏性事件灶似,在
EventBus # subscribe
方法中,如果sticky = true
眼虱,則會直接調(diào)用該類中的sticky = true
訂閱方法喻奥,具體實現(xiàn)在EventBus # checkPostStickyEventToSubscription
方法中。
注意:黏性事件捏悬,如果不需要接收撞蚕,則需要調(diào)用EventBus.getDefault().removeStickyEvent()
進行事件移除,否則每次進入該頁面过牙,都會收到該事件甥厦。
三、EventBus 事件發(fā)送過程
EventBus 通過調(diào)用 post(普通事件)寇钉、postSticky(粘性事件) 來發(fā)送事件刀疙。
EventBus.java
public void post(Object event) {
//獲得當前發(fā)送線程相關狀態(tài)(ThreadLocal保證線程安全)
PostingThreadState postingState = currentPostingThreadState.get();
//將事件添加到隊列中
List<Object> eventQueue = postingState.eventQueue;
eventQueue.add(event);
if (!postingState.isPosting) {
postingState.isMainThread = Looper.getMainLooper() == Looper.myLooper();
postingState.isPosting = true;
if (postingState.canceled) {
throw new EventBusException("Internal error. Abort state was not reset");
}
try {
//一直將隊列中發(fā)送完
while (!eventQueue.isEmpty()) {
//發(fā)送單個事件
postSingleEvent(eventQueue.remove(0), postingState);
}
} finally {
postingState.isPosting = false;
postingState.isMainThread = false;
}
}
}
注意:這里的 PostingThreadState
是通過 ThreadLocal(一個線程內(nèi)部的數(shù)據(jù)存儲類,通過它可以在指定的線程中存儲數(shù)據(jù)) 來獲取每個線程中的 PostingThreadState
狀態(tài)扫倡。
繼續(xù)看發(fā)送事件的方法:
EventBus.java
private void postSingleEvent(Object event, PostingThreadState postingState) throws Error {
Class<?> eventClass = event.getClass();
boolean subscriptionFound = false;
//是否觸發(fā)訂閱了該事件(eventClass)的父類,以及接口的類的響應方法
if (eventInheritance) { // 這個變量默認為 true
//查找eventClass類所有的父類以及接口
List<Class<?>> eventTypes = lookupAllEventTypes(eventClass);
int countTypes = eventTypes.size();
//循環(huán)postSingleEventForEventType
for (int h = 0; h < countTypes; h++) {
Class<?> clazz = eventTypes.get(h);
//只要右邊有一個為true,subscriptionFound就為true
subscriptionFound |= postSingleEventForEventType(event, postingState, clazz);
}
} else {
//post單個
subscriptionFound = postSingleEventForEventType(event, postingState, eventClass);
}
//如果沒發(fā)現(xiàn)谦秧,訂閱者
if (!subscriptionFound) {
if (logNoSubscriberMessages) {
Log.d(TAG, "No subscribers registered for event " + eventClass);
}
if (sendNoSubscriberEvent && eventClass != NoSubscriberEvent.class &&
eventClass != SubscriberExceptionEvent.class) {
//發(fā)送一個NoSubscriberEvent事件,如果我們需要處理這種狀態(tài),接收這個事件就可以了
post(new NoSubscriberEvent(this, event));
}
}
}
postSingleEventForEventType
方法:
private boolean postSingleEventForEventType(Object event, PostingThreadState postingState, Class<?> eventClass) {
CopyOnWriteArrayList<Subscription> subscriptions;
//獲取訂閱了這個事件的Subscription列表.(這里的 eventClass,對應上面的`String.class`)
synchronized (this) {
subscriptions = subscriptionsByEventType.get(eventClass);
}
//判斷訂閱者是否為null
if (subscriptions != null && !subscriptions.isEmpty()) {
for (Subscription subscription : subscriptions) {
postingState.event = event;
postingState.subscription = subscription;
//是否被中斷
boolean aborted = false;
try {
//分發(fā)給訂閱者
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;
}
//將事件 post給具體的訂閱者撵溃,涉及到線程切換
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 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);
}
}
invokeSubscriber
方法:
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);
}
}
從 subscriptionsByEventType
獲得訂閱這個 事件(event) 的 Subscription
訂閱者列表疚鲤,通過 postToSubscription
方法將事件分發(fā)給訂閱者,這個方法中涉及到了線程的不同缘挑,最后是通過反射調(diào)用了 invoke
訂閱者的方法
其中 ThreadMode
是一個枚舉類集歇,包含四種類型:
-
POSTING
:默認的 ThreadMode,表示在執(zhí)行 Post 操作的線程直接調(diào)用訂閱者的事件響應方法语淘,不論該線程是否為主線程(UI 線程)诲宇。當該線程為主線程時,響應方法中不能有耗時操作惶翻,否則有卡主線程的風險姑蓝。適用場景:對于是否在主線程執(zhí)行無要求,但若 Post 線程為主線程吕粗,不能耗時的操作它掂; -
MAIN
:在主線程中執(zhí)行響應方法。如果發(fā)布線程就是主線程,則直接調(diào)用訂閱者的事件響應方法虐秋,否則通過主線程的 Handler 發(fā)送消息在主線程中處理——調(diào)用訂閱者的事件響應函數(shù)榕茧。顯然,MainThread類的方法也不能有耗時操作客给,以避免卡主線程用押。適用場景:必須在主線程執(zhí)行的操作; -
BACKGROUND
:在后臺線程中執(zhí)行響應方法靶剑。如果發(fā)布線程不是主線程蜻拨,則直接調(diào)用訂閱者的事件響應函數(shù),否則啟動唯一的后臺線程去處理桩引。由于后臺線程是唯一的缎讼,當事件超過一個的時候,它們會被放在隊列中依次執(zhí)行坑匠,因此該類響應方法雖然沒有PostThread類和MainThread類方法對性能敏感血崭,但最好不要有重度耗時的操作或太頻繁的輕度耗時操作,以造成其他操作等待厘灼。適用場景:操作輕微耗時且不會過于頻繁夹纫,即一般的耗時操作都可以放在這里; -
ASYNC
:不論發(fā)布線程是否為主線程设凹,都使用一個空閑線程來處理舰讹。和BackgroundThread不同的是,Async類的所有線程是相互獨立的闪朱,因此不會出現(xiàn)卡線程的問題月匣。適用場景:長耗時操作,例如網(wǎng)絡訪問奋姿。
Poster 包含Poster桶错、BackgroundPoster、AsyncPoster
在postToSubscription
方法中也起了重要作用胀蛮,簡單分析一下mainThreadPoster.enqueue(subscription, event);
//EventBus.java
private final Poster mainThreadPoster;
//創(chuàng)建
mainThreadPoster = mainThreadSupport != null ? mainThreadSupport.createPoster(this) : null;
MainThreadSupport
是一個接口,實現(xiàn)類為: AndroidHandlerMainThreadSupport
public interface MainThreadSupport {
boolean isMainThread();
Poster createPoster(EventBus eventBus);
class AndroidHandlerMainThreadSupport implements MainThreadSupport {
private final Looper 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); //重點
}
}
}
上述代碼重點在 new HandlerPoster(eventBus, looper, 10);
public class HandlerPoster extends Handler implements Poster {
private final PendingPostQueue queue;
private final int maxMillisInsideHandleMessage;
private final EventBus eventBus;
private boolean handlerActive;
protected HandlerPoster(EventBus eventBus, Looper looper, int maxMillisInsideHandleMessage) {
super(looper);
this.eventBus = eventBus;
this.maxMillisInsideHandleMessage = maxMillisInsideHandleMessage;
queue = new PendingPostQueue();
}
public void enqueue(Subscription subscription, Object event) {
PendingPost pendingPost = PendingPost.obtainPendingPost(subscription, event);
synchronized (this) {
queue.enqueue(pendingPost);
if (!handlerActive) {
handlerActive = true;
if (!sendMessage(obtainMessage())) {
throw new EventBusException("Could not send handler message");
}
}
}
}
@Override
public void handleMessage(Message msg) {
boolean rescheduled = false;
try {
long started = SystemClock.uptimeMillis();
while (true) {
PendingPost pendingPost = queue.poll();
if (pendingPost == null) {
synchronized (this) {
// Check again, this time in synchronized
pendingPost = queue.poll();
if (pendingPost == null) {
handlerActive = false;
return;
}
}
}
eventBus.invokeSubscriber(pendingPost);
long timeInMethod = SystemClock.uptimeMillis() - started;
if (timeInMethod >= maxMillisInsideHandleMessage) {
if (!sendMessage(obtainMessage())) {
throw new EventBusException("Could not send handler message");
}
rescheduled = true;
return;
}
}
} finally {
handlerActive = rescheduled;
}
}
}
HandlerPoster
需要關注的有:
- 該類是通過 Handler 機制來實現(xiàn)糯钙。
-
HandlerPoster # enqueue
方法粪狼,將事件添加到了隊列中,并通過handler發(fā)送message 任岸,通知handleMessage
進行處理(此時線程達到了切換)再榄。 -
handleMessage
中,處理消息享潜, 比較關鍵的代碼是eventBus.invokeSubscriber(pendingPost);
//EventBus.java
void invokeSubscriber(PendingPost pendingPost) {
Object event = pendingPost.event; // 這里的event困鸥,對應時間,也就是上面的 String.class
Subscription subscription = pendingPost.subscription;
PendingPost.releasePendingPost(pendingPost);
if (subscription.active) {
invokeSubscriber(subscription, event);//通過反射,調(diào)用方法
}
}
四疾就、EventBus 反注冊
簡單來說澜术,就是把訂閱者從 typesBySubscriber
移除,下次再發(fā)送消息的時候猬腰,就不會通知了鸟废。
EventBus.java
/** 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 移除
typesBySubscriber.remove(subscriber);
} else {
Log.w(TAG, "Subscriber to unregister was not registered before: " + subscriber.getClass());
}
}
unsubscribeByEventType
方法:
/** Only updates subscriptionsByEventType, not typesBySubscriber! Caller must update typesBySubscriber. */
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--;
}
}
}
}