1. 注册及查找事件
1.1 EventBus初始化
- getDefault: 通过单例模式获取实例,同时里面采用Builder模式构造部分初始化参数,方便定制部分配置信息
//Builder模式,在EventBusBuilder里面完成一些默认的初始化操作 private static final EventBusBuilder DEFAULT_BUILDER = new EventBusBuilder(); public static EventBus getDefault() { //通过DCL单例模式创建EventBus实例 } public EventBus() { this(DEFAULT_BUILDER); } EventBus(EventBusBuilder builder) { //通过EventBusBuilder完成的初始化构造 }
1.2 EventBus注册
-
register:根据订阅者类信息,查询对应的订阅方法信息,遍历注册订阅方法
public void register(Object subscriber) { //根据订阅者的类名信息查询订阅方法 Class> subscriberClass = subscriber.getClass(); List
subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass); synchronized (this) { //遍历并注册这些订阅方法 for (SubscriberMethod subscriberMethod : subscriberMethods) { subscribe(subscriber, subscriberMethod); } } } -
SubscriberMethod:封装了订阅方法的基本类型信息,即@Subscribe中所注解的内容
public SubscriberMethod(Method method, Class> eventType, ThreadMode threadMode, int priority, boolean sticky) { this.method = method; this.threadMode = threadMode; this.eventType = eventType; this.priority = priority; this.sticky = sticky; }
1.3 查询订阅者所有的订阅方法
-
findSubscriberMethods: 查询订阅者所有的订阅方法,三种查询方式:缓存,通过注解器索引,反射
//METHOD_CACHE缓存了订阅及其所有订阅方法 private static final Map
, List > METHOD_CACHE = new ConcurrentHashMap<>(); List findSubscriberMethods(Class> subscriberClass) { //首先查找缓存 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()) {//如果当前订阅者没有声明订阅方法,则抛出异常 } else { //将订阅者及订阅方法存入缓存中 METHOD_CACHE.put(subscriberClass, subscriberMethods); ... } }
1.3.1 通过注解索引的方式获取订阅者的订阅方法
-
findUsingInfo:获取订阅者信息,并且对其父类进行向上查询,最后将所有订阅方法信息封装到subscriberMethods列表中返回
private List
findUsingInfo(Class> subscriberClass) { FindState findState = prepareFindState();//通过对象池的方式复用FindState 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.clazz改为subscriberClass的父类Class,再进行遍历 findState.moveToSuperclass(); } return getMethodsAndRelease(findState);//回收FindState对象到对象池中,并返回subscriberMethods列表 } ... //实现对象池 private static final FindState[] FIND_STATE_POOL = new FindState[POOL_SIZE];// POOL_SIZE = 4; private FindState prepareFindState() { synchronized (FIND_STATE_POOL) { for (int i = 0; i < POOL_SIZE; i++) { FindState state = FIND_STATE_POOL[i]; if (state != null) { FIND_STATE_POOL[i] = null; return state; } } } return new FindState(); } -
getSubscriberInfo:遍历订阅者索引,返回查找的订阅者的信息
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; }
-
FindState 主要用来辅助存储订阅者信息
static class FindState { final List
subscriberMethods = new ArrayList<>(); final Map anyMethodByEventType = new HashMap<>(); final Map subscriberClassByMethodKey = new HashMap<>(); final StringBuilder methodKeyBuilder = new StringBuilder(128); ... void moveToSuperclass() { ... }// 修改findState.clazz为subscriberClass的父类Class }
1.3.2 通过反射获取订阅者的订阅方法
-
findUsingReflection
//FindState主要用来辅助存储订阅者信息 private List
findUsingReflection(Class> subscriberClass) { FindState findState = prepareFindState();//通过对象池的方式复用FindState findState.initForSubscriber(subscriberClass);//初始化参数并将订阅者类信息导入 while (findState.clazz != null) { findUsingReflectionInSingleClass(findState);//通过反射查询订阅者的订阅方法 // 将findState.clazz改为subscriberClass的父类Class,再进行遍历 findState.moveToSuperclass(); } return getMethodsAndRelease(findState);//回收FindState对象到对象池中,并返回subscriberMethods列表 } -
findUsingReflectionInSingleClass:通过反射查询订阅者的订阅方法
private void findUsingReflectionInSingleClass(FindState findState) { Method[] methods; try { // This is faster than getMethods, especially when subscribers are fat classes like Activities methods = findState.clazz.getDeclaredMethods();//获取所有声明方法 } catch (Throwable th) { // Workaround for java.lang.NoClassDefFoundError methods = findState.clazz.getMethods(); findState.skipSuperClasses = true; } for (Method method : methods) { int modifiers = method.getModifiers(); //校验方法修饰属性,是否PUBLIC及MODIFIERS_IGNORE // MODIFIERS_IGNORE = Modifier.ABSTRACT | Modifier.STATIC | BRIDGE | SYNTHETIC; if ((modifiers & Modifier.PUBLIC) != 0 && (modifiers & MODIFIERS_IGNORE) == 0) { Class>[] parameterTypes = method.getParameterTypes();//校验方法参数 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)) { //抛出异常 } } else if (strictMethodVerification && method.isAnnotationPresent(Subscribe.class)) { //抛出异常 } } }
1.4 注册订阅方法:
-
subscribe:将订阅者和订阅方法封装成对象,并将相同事件类型的封装对象根据事件优先级封装到CopyOnWriteArrayList集合中,再将事件类型和CopyOnWriteArrayList封装到map集合中
Map
2. 发布通知消息
-
post:通过在ThreadLocal中封装一个事件队列,去添加和执行相应的事件
public void post(Object event) { //在ThreadLocal中封装一个线程状态信息,里面包含一个事件队列 PostingThreadState postingState = currentPostingThreadState.get(); List
-
postSingleEvent
private void postSingleEvent(Object event, PostingThreadState postingState) throws Error { Class> eventClass = event.getClass(); boolean subscriptionFound = false; if (eventInheritance) { //遍历查找它的父类添加到列表 List
> 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); } ... //找不到事件时异常处理 NoSubscriberEvent } private boolean postSingleEventForEventType(Object event, PostingThreadState postingState, Class> eventClass) { CopyOnWriteArrayList subscriptions; synchronized (this) { //获取对应的订阅者 subscriptions = subscriptionsByEventType.get(eventClass); } ... for (Subscription subscription : subscriptions) { postingState.event = event; postingState.subscription = subscription; boolean aborted = false; try {//通知订阅者 postToSubscription(subscription, event, postingState.isMainThread); aborted = postingState.canceled; } finally { ...//重置postingState属性 } if (aborted)break; } ... } -
postToSubscription:通知订阅者,对于不同线程发布消息会调用相应的线程事件队列去执行
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继承自Handler mainThreadPoster.enqueue(subscription, event); } break; case MAIN_ORDERED: if (mainThreadPoster != null) { mainThreadPoster.enqueue(subscription, event); } else { invokeSubscriber(subscription, event); } break; case BACKGROUND: if (isMainThread) { //如果不是后台线程,则加入到后台线程行队列中执行 backgroundPoster.enqueue(subscription, event); } else { invokeSubscriber(subscription, event); } break; case ASYNC: asyncPoster.enqueue(subscription, event); break; ... } } ... void invokeSubscriber(Subscription subscription, Object event) { ... subscription.subscriberMethod.method.invoke(subscription.subscriber, event); }
3. 发布粘性通知
-
postSticky: 粘性事件会通过单独的stickyEvents集合进行存储,同时会在事件订阅的时候进行check post,继而实现粘性这一效果
public void postSticky(Object event) { synchronized (stickyEvents) { stickyEvents.put(event.getClass(), event); //添加到粘性事件列表,在上述注册订阅方法时,会通过列表去通知信息 } // Should be posted after it is putted, in case the subscriber wants to remove immediately post(event);//发布通知,当前已经订阅的订阅者可以收到 } ... private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) { ... if (subscriberMethod.sticky) {//处理粘性事件 if (eventInheritance) { // 迭代所有事件可能会导致很多粘性事件的效率低下,因此应该更改数据结构以允许更有效的查找 Set
, Object>> entries = stickyEvents.entrySet(); for (Map.Entry , 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); } } }