EventBus源码分析
问题1:EventBus可以创建多个实例吗?
/**
* Creates a new EventBus instance; each instance is a separate scope in which events are delivered. To use a
* central bus, consider {@link #getDefault()}.
*/
public EventBus() {
this(DEFAULT_BUILDER);
}
这里会发现EventBus的构造方法是公有的,也就是说我们自己可以自己new一个EventBus的实例,当然EventBus也提供了EventBusBuilder供我们构造使用。这里特意把构造方法的注释放了上来,大概翻译一下吧。
创建一个EventBus实例,每一个实例的事件传递都在自己的实例范围,如果想统一管理,可以使用getDefault()方法。
这里通过注释我们就可以解释第五个问题了,当然只是从注释层面,EventBus是可以创建多个实例的,并且多个实例的发送的事件是互不干扰的
再看下 findSubscriberMethods() 这个方法,会通过类对象的 class 去解析这个类中的所有 Subscribe 注解方法的所有属性值,一个注解方法对应一个 SubscriberMethod 对象,包括 threadMode,priority,sticky,eventType,methodString。
2、源码分析
首先来看register
//subscriber 传入的就是当前注册的Activity
public void register(Object subscriber) {
Class<?> subscriberClass = subscriber.getClass();
//查找传入的Activity中一共有多少个含有@Subscribe注解的监听方法,有几个@Subscribe注解subscriberMethods的size就为几
List<SubscriberMethod> subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass);
synchronized (this) {
for (SubscriberMethod subscriberMethod : subscriberMethods) {
// subsciber 对 List<SubscriberMethod> 中每个 SubscriberMethod 进行订阅
subscribe(subscriber, subscriberMethod);
}
}
}
说明下SubscriberMethod这个类,类中有个参数eventType指的就是事件类型,即调用post("eventType")方法中传入的参数,也是@Subscribe注解的接收数据的方法中的入参,以下是debug中日志信息,很好的说明了一切:
image.png再来看看Subscription这个类,可以理解成订阅者信息类
//指的是当前订阅者的类
final Object subscriber;
final SubscriberMethod subscriberMethod;
考以下几个问题:
对于同一个 Event,当前类对该对象使用了多个方法进行了多次订阅,那么如果该 Event 被发射的时候,当前类会如何调用这些方法?
对于同一个 Event,父类对该对象进行了一次订阅,子类重写该订阅方法,那么如果该 Event 被发射的时候,父类子类当中会如何处理这些方法?
1、会的
2、会调用子类的,不会调用父类的
注册完之后就需要做订阅操作,subscribe
// Must be called in synchronized block
private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) {
Class<?> eventType = subscriberMethod.eventType;
Subscription newSubscription = new Subscription(subscriber, subscriberMethod);
//说明1
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;
}
}
//说明2
List<Class<?>> subscribedEvents = typesBySubscriber.get(subscriber);
if (subscribedEvents == null) {
subscribedEvents = new ArrayList<>();
typesBySubscriber.put(subscriber, subscribedEvents);
}
subscribedEvents.add(eventType);
// 省略 sticky 事件
说明1中:subscriptionsByEventType 是一个Map<Class<?>, CopyOnWriteArrayList<Subscription>>类型,key是eventType,value是订阅者集合
说明2中:typesBySubscriber 是一个Map<Object, List<Class<?>>>类型
key为订阅者类,value为eventType集合,主要是在关闭界面时反注册的时候使用