前言
今天来学习一下事件总线EventBus的源码流程,对于EventBus,想必同学们都非常熟悉了。那么我们通过分析EventBus的源码,来思考以下几个问题。
- EventBus用到了哪几种设计模式?
- EventBus是如何识别订阅者的?
- EventBus如何注销订阅者呢?
构造方法
public EventBus() {
this(DEFAULT_BUILDER);
}
EventBus(EventBusBuilder builder) {
this.currentPostingThreadState = new ThreadLocal<EventBus.PostingThreadState>() {
protected EventBus.PostingThreadState initialValue() {
return new EventBus.PostingThreadState();
}
};
this.logger = builder.getLogger();
this.subscriptionsByEventType = new HashMap();
this.typesBySubscriber = new HashMap();
this.stickyEvents = new ConcurrentHashMap();
this.mainThreadSupport = builder.getMainThreadSupport();
this.mainThreadPoster = this.mainThreadSupport != null ? this.mainThreadSupport.createPoster(this) : null;
this.backgroundPoster = new BackgroundPoster(this);
this.asyncPoster = new AsyncPoster(this);
this.indexCount = builder.subscriberInfoIndexes != null ? builder.subscriberInfoIndexes.size() : 0;
this.subscriberMethodFinder = new SubscriberMethodFinder(builder.subscriberInfoIndexes, builder.strictMethodVerification, builder.ignoreGeneratedIndex);
this.logSubscriberExceptions = builder.logSubscriberExceptions;
this.logNoSubscriberMessages = builder.logNoSubscriberMessages;
this.sendSubscriberExceptionEvent = builder.sendSubscriberExceptionEvent;
this.sendNoSubscriberEvent = builder.sendNoSubscriberEvent;
this.throwSubscriberException = builder.throwSubscriberException;
this.eventInheritance = builder.eventInheritance;
this.executorService = builder.executorService;
}
复制代码
可以看出EventBus实际上只有一个构造方法,并且从构造方法中我们可以看到许多熟悉的属性。比如mainThreadSupport、mainThreadPoster、backgroundPoster,它们像不像EventBus的几种线程模式?而且从executorService来看,我们可以猜测下EventBus存在自己的线程池。
EventBus.getDefault()
public static EventBus getDefault() {
if (defaultInstance == null) {
Class var0 = EventBus.class;
synchronized(EventBus.class) {
if (defaultInstance == null) {
defaultInstance = new EventBus();
}
}
}
return defaultInstance;
}
复制代码
从源码中我们可以看出,使用了单例模式来获取EventBus实例。
register()
public void register(Object subscriber) {
//subscriber一般是指订阅者,比如Activity
//这里获取了subscriber的class
Class<?> subscriberClass = subscriber.getClass();
//获得了一个具有订阅方法的subscriberMethods集合
List<SubscriberMethod> subscriberMethods = this.subscriberMethodFinder.findSubscriberMethods(subscriberClass);
synchronized(this) {
Iterator var5 = subscriberMethods.iterator();
while(var5.hasNext()) {
SubscriberMethod subscriberMethod = (SubscriberMethod)var5.next();
//开始进行注册
this.subscribe(subscriber, subscriberMethod);
}
}
}
复制代码
EventBus的注册流程主要分为以下几步:
- 获取订阅者的class对象
- 获取订阅者所有的订阅方法
- 进行注册
findSubscriberMethods()
List<SubscriberMethod> findSubscriberMethods(Class<?> subscriberClass) {
//首先查看缓存中是否存在
List<SubscriberMethod> subscriberMethods = (List)METHOD_CACHE.get(subscriberClass);
if (subscriberMethods != null) {
return subscriberMethods;
} else {
//ignoreGeneratedIndex默认为false,所以我们来看findUsingInfo()方法
if (this.ignoreGeneratedIndex) {
subscriberMethods = this.findUsingReflection(subscriberClass);
} else {
subscriberMethods = this.findUsingInfo(subscriberClass);
}
if (subscriberMethods.isEmpty()) {
throw new EventBusException("Subscriber " + subscriberClass + " and its super classes have no public methods with the @Subscribe annotation");
} else {
//最后将subscriberClass、subscriberMethods添加到缓存中
METHOD_CACHE.put(subscriberClass, subscriberMethods);
return subscriberMethods;
}
}
}
复制代码
findUsingInfo()
private List<SubscriberMethod> findUsingInfo(Class<?> subscriberClass) {
//...
} else {
this.findUsingReflectionInSingleClass(findState);
}
}
return this.getMethodsAndRelease(findState);
}
复制代码
我们主要来看findUsingReflectionInSingleClass()方法,源码如下:
private void findUsingReflectionInSingleClass(SubscriberMethodFinder.FindState findState) {
Method[] methods;
try {
//通过反射获得订阅者所有的方法
methods = findState.clazz.getDeclaredMethods();
} catch (Throwable var12) {
methods = findState.clazz.getMethods();
findState.skipSuperClasses = true;
}
//...
if (parameterTypes.length == 1) {
//获得了注解
Subscribe subscribeAnnotation = (Subscribe)method.getAnnotation(Subscribe.class);
if (subscribeAnnotation != null) {
Class<?> eventType = parameterTypes[0];
if (findState.checkAdd(method, eventType)) {
//获得了ThreadMode属性
ThreadMode threadMode = subscribeAnnotation.threadMode();
//最后将method, eventType, threadMode, priority(),sticky这些属性包装成一个SubscriberMethod,并添加到subscriberMethods集合中
findState.subscriberMethods.add(new SubscriberMethod(method, eventType, threadMode, subscribeAnnotation.priority(), subscribeAnnotation.sticky()));
}
}
//...
复制代码
查找带有注解的订阅方法主要流程有以下几步:
- 首先查看缓存中是否存在subscriberMethods,如果存在就返回缓存,不存在则进行下一步
- 通过反射获取订阅者所有的方法
- 查找带有注解的订阅方法,并将订阅方法相关属性信息包装成SubscriberMethod对象,添加到集合
subscribe()
private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) {
Class<?> eventType = subscriberMethod.eventType;
//将subscriber和subscriberMethod添加到Subscription
Subscription newSubscription = new Subscription(subscriber, subscriberMethod);
//将Subscription添加到CopyOnWriteArrayList集合
CopyOnWriteArrayList<Subscription> subscriptions = (CopyOnWriteArrayList)this.subscriptionsByEventType.get(eventType);
if (subscriptions == null) {
subscriptions = new CopyOnWriteArrayList();
this.subscriptionsByEventType.put(eventType, subscriptions);
} else if (subscriptions.contains(newSubscription)) {
throw new EventBusException("Subscriber " + subscriber.getClass() + " already registered to event " + eventType);
}
//...
}
复制代码
在源码中,将订阅者和订阅方法添加到了一个Subscription中,然后又从subscriptionsByEventType集合中获得一个Subscription类型的subscriptions集合。
private final Map<Class<?>, CopyOnWriteArrayList<Subscription>> subscriptionsByEventType;
复制代码
subscriptionsByEventType是一个key为class,value为CopyOnWriteArrayList集合的Map集合。在subscribe()方法中我们也看到了最终订阅者和订阅方法被添加到了一个subscriptions的CopyOnWriteArrayList集合中,也就是说subscribe()方法主要作用是保存订阅者和订阅方法相关信息,然后在EventBus发出事件时,可以识别已经注册的订阅者。
unregister()
public synchronized void unregister(Object subscriber) {
List<Class<?>> subscribedTypes = (List)this.typesBySubscriber.get(subscriber);
if (subscribedTypes != null) {
Iterator var3 = subscribedTypes.iterator();
while(var3.hasNext()) {
Class<?> eventType = (Class)var3.next();
this.unsubscribeByEventType(subscriber, eventType);
}
this.typesBySubscriber.remove(subscriber);
} else {
this.logger.log(Level.WARNING, "Subscriber to unregister was not registered before: " + subscriber.getClass());
}
复制代码
首先我们来看一下unsubscribeByEventType()方法
private void unsubscribeByEventType(Object subscriber, Class<?> eventType) {
List<Subscription> subscriptions = (List)this.subscriptionsByEventType.get(eventType);
if (subscriptions != null) {
int size = subscriptions.size();
for(int i = 0; i < size; ++i) {
Subscription subscription = (Subscription)subscriptions.get(i);
if (subscription.subscriber == subscriber) {
subscription.active = false;
subscriptions.remove(i);
--i;
--size;
}
}
}
复制代码
看到这里,我们是不是明白了unregister()方法?unregister()方法就是删除EventBus中已经注册的订阅者相关信息,与register()方法作用相反。
总结
本篇文章我们分析了EventBus的register()和unregister()方法的源码流程,明白了两个方法的主要作用。了解了EventBus是如何注册订阅者,并识别订阅者的。在下一篇文章中,我们将会分析EventBus是如何分发事件的。