EventBus原理
设计模式:单例模式、建造者模式、观察者模式
单例:
建造者:
register:
流程图:
源码:
public void register(Object subscriber) {
// 用 subscriberMethodFinder 提供的方法,找到在 subscriber 这个类里面,订阅的内容。
Class subscriberClass = subscriber.getClass();
List subscriberMethods =subscriberMethodFinder.findSubscriberMethods(subscriberClass);
synchronized (this) {
for (SubscriberMethod subscriberMethod : subscriberMethods) {
// 遍历这些方法,subscribe 这些事件
subscribe(subscriber, subscriberMethod);
}
}
}
subscribe():生成3个集合类
private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) {
//获取subsrciberMethod传递的自定义EventType参数的运行时的类
Class eventType = subscriberMethod.eventType;
//Subscription用于绑定subscriber和sucriberMethod,一个订阅者可以有多个subscriberMethod
Subscription newSubscription = new Subscription(subscriber, subscriberMethod);
//根据EventType的运行时类取到该类所有的subscriptioins,subscriptionsByEventType是HashMap中的key
CopyOnWriteArrayList subscriptions = subscriptionsByEventType.get(eventType);
if (subscriptions == null) {
subscriptions = new CopyOnWriteArrayList<>();
//若根据EventType找不到subscriptions,则eventType作key,subscriptions作value添加到subscriptionByEventType中。
subscriptionsByEventType.put(eventType, subscriptions);
} else {
if (subscriptions.contains(newSubscription)) {
//已经存在newSubscription,抛出异常该订阅者已经注册,不可重复注册同一个subscriber
throw new EventBusException("Subscriber " + subscriber.getClass() + " already registered to event "
+ eventType);
}
}
int size = subscriptions.size();
for (int i = 0; i <= size; i++) {
//循环subscriptions,根据标记优先级的priority从高到低,将新的subscription插入到subscriptions中
if (i == size || subscriberMethod.priority > subscriptions.get(i).subscriberMethod.priority) {
subscriptions.add(i, newSubscription);
break;
}
}
//typesBySubscriber是一个HashMap,根据subscriber做key,获取该subscriber对应的所有的订阅事件的类型
List> subscribedEvents = typesBySubscriber.get(subscriber);
if (subscribedEvents == null) {
subscribedEvents = new ArrayList<>();
//该订阅者之前的订阅事件类型列表为空,则将当前订阅类型添加到typesBySubscriber中
typesBySubscriber.put(subscriber, subscribedEvents);
}
subscribedEvents.add(eventType);
//如果该方法被标识为sticky事件
if (subscriberMethod.sticky) {
if (eventInheritance) { eventInheritance标识是否考虑EventType的类层次结构
//循环所有的sticky黏性事件
Set, Object>> entries = stickyEvents.entrySet();
for (Map.Entry, Object> entry : entries) {
Class candidateEventType = entry.getKey();
//如果当前事件是其他事件的同类型的或者是他们的父类
if (eventType.isAssignableFrom(candidateEventType)) {
Object stickyEvent = entry.getValue();
heckPostStickyEventToSubscription(newSubscription, stickyEvent);
}
}
} else {
Object stickyEvent = stickyEvents.get(eventType);
checkPostStickyEventToSubscription(newSubscription, stickyEvent);
}
}
}
- Map<Class<?>,CopyOnWriteArrayList<Subscription>> subscriptionByEventType -> Key:Event,Value:Subscribe集合,当发送这个Event时,可在Map中找到相应的Subscriber集合,将订阅方法可接收时间类型和对应的Subscription集合保存到subscriptionsByEventType中去。
2. Map<Object,List<Class<?>>> typeBySubscriber -> Key:Subscriber,Value:Event,当注册和反注册时,都会操作typesBySubscriber,将注册类对象和注册类中订阅事件方法的参数类型集合保存到typesBySubscriber。
3. Map, Object>stickyEvents -> 如果是粘性事件subscriberMethod.sticky=true,则从stickyEvent中取出对应类型时间,用迭代器一一进行执行订阅事件的方法。
订阅的方法信息
public SubscriberMethod(String methodName, Class<?> eventType, ThreadMode threadMode,
int priority, boolean sticky) {
this.methodName = methodName;
this.threadMode = threadMode;
this.eventType = eventType;
this.priority = priority;
this.sticky = sticky;
}
findSubscriberMethods 这个方法是实现 EventBus 的核心代码,这里面包含了 EventBus 隐式定义的交互协议。从这个方法里面,可以看到如何争取地使用EventBus。
List<SubscriberMethod> findSubscriberMethods(Class<?> subscriberClass) { {
// 如果这个 Class 对应的方法被缓存,直接返回。
List subscriberMethods =METHOD_CACHE.get(subscriberClass);
if (subscriberMethods !=null) {
return subscriberMethods;
}
//ignoreGeneratedIndex默认为false,是否从索引勒种取出当前注册类对应的事件订阅方法信息
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;
}
}
post&postSticky:
流程图:
postSticky:
/**
* Posts the given event to the event bus and holds on to the event (because it is sticky). The most recent sticky
* event of an event's type is kept in memory for future access by subscribers using {@link Subscribe#sticky()}.
*/
public void postSticky(Object event) {
synchronized (stickyEvents) {
stickyEvents.put(event.getClass(), event);//加入粘性事件stickyEvents:Map中
}
// Should be posted after it is putted, in case the subscriber wants to remove immediately
post(event);
}
######post:
/** Posts the given event to the event bus. */
public void post(Object event) {
//从currentPostingThreadState:ThreadLocal中获取发送线程的状态
PostingThreadState postingState =currentPostingThreadState.get();
List eventQueue = postingState.eventQueue; //从获取发送线程中队列
eventQueue.add(event);//将事件加入到发送线程中队列
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;
}
}
}
private void postSingleEvent(Object event, PostingThreadState postingState) throws Error {
/*获取事件的Class,所有事件的Class对应的订阅者列表在register的时候是已经保存了的*/
Class<?> eventClass = event.getClass();
/*根据事件的Class找到订阅者的标志状态,初始化为false*/
boolean subscriptionFound = false;
/*
* 比如 A extends B implements C 发布者post(A),那么找订阅者的时候不仅要找订阅了事件A的订阅者
* 还要找订阅了B和C的订阅者*/
if (eventInheritance) {
/*找到事件的所有父类和所有实现的接口*/
List<Class<?>> eventTypes = lookupAllEventTypes(eventClass);
int countTypes = eventTypes.size();
for (int h = 0; h < countTypes; h++) {
Class<?> clazz = eventTypes.get(h);
subscriptionFound |= postSingleEventForEventType(event, postingState, clazz);
}
/*不考虑事件的继承性的话,那么处理起来就比较简单了*/
} else {
subscriptionFound = postSingleEventForEventType(event, postingState, eventClass);
}
if (!subscriptionFound) {
if (logNoSubscriberMessages) {
Log.d(TAG, "No subscribers registered for event " + eventClass);
}
if (sendNoSubscriberEvent && eventClass != NoSubscriberEvent.class &&
eventClass != SubscriberExceptionEvent.class) {
post(new NoSubscriberEvent(this, event));
}
}
}
前边说过了EventBus维护了两个重要的map。其中一个就是事件的Class到能处理此事件的所有订阅者列表的map,因此不仅要把事件的Class存入map中的订阅者列表,还要把事件的所有父类和所有实现的接口的Class存入订阅者列表。下边是找到某个类所有父类和所有实现接口的方法:
/** Looks up all Class objects including super classes and interfaces. Should also work for interfaces. */
/*找到事件的所有父类和实现的接口,以Class列表的形式返回*/
private List<Class<?>> lookupAllEventTypes(Class<?> eventClass) {
/*private static final Map<Class<?>, List<Class<?>>> eventTypesCache = new HashMap<Class<?>, List<Class<?>>>();*/
synchronized (eventTypesCache) {
/*查看缓存,看能否命中*/
List<Class<?>> eventTypes = eventTypesCache.get(eventClass);
/*缓存不命中*/
if (eventTypes == null) {
/*创建事件类型列表*/
eventTypes = new ArrayList<Class<?>>();
Class<?> clazz = eventClass;
/*getSuperclass()返回null的情况:Class表示的类为Object、基本数据类型、接口或者void*/
while (clazz != null) {
eventTypes.add(clazz);
/*把接口对应的Class也添加进Class列表
* clazz.getInterfaces():返回clazz表示的类直接实现的接口的Class列表,不包括间接实现的接口
* */
addInterfaces(eventTypes, clazz.getInterfaces());
/** public Class<? super T> getSuperclass() :
* Returns the Class object which represents the superclass of the
* class represented by this Class. If this Class represents
* the Object class, a primitive type, an interface or void then the
* method returns null. If this Class represents an array
* class then the Object class is returned.
*/
clazz = clazz.getSuperclass();
}
/*找到一个事件的所有父类和所有实现接口的Class挺复杂的,循环加递归的,还是加入缓存机制提高性能吧*/
eventTypesCache.put(eventClass, eventTypes);
}
return eventTypes;
}
}
/** Recurses through super interfaces. 获取某个类直接实现的所有接口,包括间接实现的
* @param eventTypes
* @param interfaces*/
static void addInterfaces(List<Class<?>> eventTypes, Class<?>[] interfaces) {
/*对这个类直接实现的每个接口开始遍历*/
for (Class<?> interfaceClass : interfaces) {
/*如果这个接口还没有添加到列表接把他添加到列表*/
if (!eventTypes.contains(interfaceClass)) {
eventTypes.add(interfaceClass);
/*把这个接口所直接实现的所有接口的Class也添加进列表 递归调用*/
addInterfaces(eventTypes, interfaceClass.getInterfaces());
}
}
}
最后调用
private void checkPostStickyEventToSubscription(Subscription newSubscription, Object stickyEvent) {
if (stickyEvent != null) {
// If the subscriber is trying to abort the event, it will fail (event is not tracked in posting state)
// --> Strange corner case, which we don't take care of here.
postToSubscription(newSubscription, stickyEvent, Looper.getMainLooper() == Looper.myLooper());
}
}
private void postToSubscription(Subscription subscription, Object event, boolean isMainThread) {
//根据@subscriber中threadMode进行区分,POSTING为当前线程执行,
//MAIN为主线程,BACKGROUND为子进程,ASYNC为异步执行。
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);
}
}
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);
}
}
unregister:
流程图:
源码:
/** 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.remove(subscriber);
} else {
logger.log(Level.WARNING, "Subscriber to unregister was not registered before: " + subscriber.getClass());
}
}
/** 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--;
}
}
}
}