前言
解除注册照理应该放到系列的最后一篇来讲,但笔者选择将其放在第四篇,是有如下原因的:
- 解除注册的代码逻辑相对简单
- 与注册形成对应关系,便于读者连贯理解
- 注册与解除注册在实际使用时,都是一次性成对书写的,这也是使用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());
}
}
梳理解除注册逻辑,规整如下:
- 根据订阅者对象,从typesBySubscriber结构中取出订阅的事件类型集合
- 如果事件类型集合非null,则遍历集合,依次根据事件类型解除相应的订阅,并根据订阅者将事件类型集合从typesBySubscriber移除
- 如果事件集合为null,说明要解除注册的订阅者之前并没有注册过EventBus
以上步骤都很好理解,我们重点来看看步骤2里面的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--;
}
}
}
}
unsubscribeByEventType的逻辑其实也非常简单,大致如下:
- 根据事件类型,从subscriptionsByEventType获取订阅信息集合subscriptions
- 遍历订阅信息集合,判断订阅信息所属的订阅者是否与当前传递进来的订阅者相同
- 若相同,则将订阅信息的active变量置位成false,代表该订阅被解除,并且从订阅信息集合中移除
二、结束语
解除注册的过程简单清晰,主要是对上一篇文章提及的几个重要成员变量的操作。
- typesBySubscriber:键是订阅者class对象、值是事件类型list的Map结构
- Subscription:订阅信息,内部封装了订阅者对象、订阅方法以及是否已经注册的布尔变量
- subscriptionsByEventType:键是事件类型class对象、值是订阅信息list的Map结构
当无法查找到订阅者的订阅事件信息时,说明该订阅者还没有注册过,打印如下log:
Subscriber to unregister was not registered before: " + subscriber.getClass()