本文原文地址在github,不知是何原因,csdn博客显示不出来本文的图片,建议大家在github查看原文以获得最佳体验。本文全文较长,建议大家收藏,有时间的时候静下心来细细研读,同时由于笔者能力有限,文中可能存在些许问题,欢迎大家在github或csdn留言交流。

概述

EventBus是一个基于订阅者-发布者模式框架,该模式定义了一种一对多的依赖关系,让多个订阅者对象同时监听一个对象,通过这种方式对订阅者和主题发布者进行充分解耦,主要用于Android组件间相互通信、线程间互相通信及其他线程与UI线程之间互相通信等。代替了传统的HandlerBroadCastReceiverInterface回调等通信方式,相比之下EventBus的优点是代码简洁,使用简单,并将事件发布和订阅充分解耦。

基本用法

1:添加依赖

implementation 'org.greenrobot:eventbus:3.1.1'

2:自定义一个数据类

/*** @author dmrfcoder* @date 2019/4/22*/public class MessageEvent {public String getEventMessage() {return eventMessage;}private final String eventMessage;public MessageEvent(String eventMessage) {this.eventMessage = eventMessage;}
}

3:注册、反注册

         @Overridepublic void onCreate(@Nullable Bundle savedInstanceState) {super.onCreate(savedInstanceState);EventBus.getDefault().register(this);}@Overridepublic void onStop() {super.onStop();EventBus.getDefault().unregister(this);}

4:添加处理事件的方法

 @Subscribepublic void receiveMessage(MessageEvent messageEvent) {receivedMessage.setText(messageEvent.getEventMessage());}

5:发送事件

 private void sendMessage() {EventBus.getDefault().post(new MessageEvent("这是来自FragmentA的消息!"));}

整个流程如下图所示:

那么接下来我们根据上图展示的事件总线来深入源码理解一下其实现方法。

EventBus.getDefault()

不管是注册(register)、反注册(unregister)还是发送消息(post),我们一般都会直接使用EventBus.getDefault()方法来获取一个EventBus对象,那么这个方法里面做了什么?源码如下:

         static volatile EventBus defaultInstance;/** Convenience singleton for apps using a process-wide EventBus instance. */public static EventBus getDefault() {if (defaultInstance == null) {synchronized (EventBus.class) {if (defaultInstance == null) {defaultInstance = new EventBus();}}}return defaultInstance;}

可以看到,这是一个很经典的单例模式,首先将defaultInstance声明为static的,并且使用volatile关键字修饰defaultInstance,就是为了保证线程安全,然后在getDefault()中使用了synchronized锁实现单例,最后返回一个EventBus对象。

值得一提的是getDefault()方法中执行了new EventBus()去实例化EventBus对象,我们看看其构造方法的源码:

     private static final EventBusBuilder DEFAULT_BUILDER = new EventBusBuilder();/*** 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(EventBusBuilder builder) {logger = builder.getLogger();subscriptionsByEventType = new HashMap<>();typesBySubscriber = new HashMap<>();stickyEvents = new ConcurrentHashMap<>();mainThreadSupport = builder.getMainThreadSupport();mainThreadPoster = mainThreadSupport != null ? mainThreadSupport.createPoster(this) : null;backgroundPoster = new BackgroundPoster(this);asyncPoster = new AsyncPoster(this);indexCount = builder.subscriberInfoIndexes != null ? builder.subscriberInfoIndexes.size() : 0;subscriberMethodFinder = new SubscriberMethodFinder(builder.subscriberInfoIndexes,builder.strictMethodVerification, builder.ignoreGeneratedIndex);logSubscriberExceptions = builder.logSubscriberExceptions;logNoSubscriberMessages = builder.logNoSubscriberMessages;sendSubscriberExceptionEvent = builder.sendSubscriberExceptionEvent;sendNoSubscriberEvent = builder.sendNoSubscriberEvent;throwSubscriberException = builder.throwSubscriberException;eventInheritance = builder.eventInheritance;executorService = builder.executorService;}

可以看到,默认的构造方法是public的,这说明EventBus并不是一个真正的单例类,它允许我们实例化多个EventBus的对象,而通过getDefault()获得的是EventBus类为我们维护的一个EventBus对象,这样做的好处是既可以让用户通过获取单例对象简便地实现消息通信,又可以支持用户根据自己的需求定制自己的EventBus,一般来说我们使用EventBus默认提供的getDefault()即可。

另外需要注意的一点是这里使用了经典的建造者(Builder)模式,我们来看一下这个EventBusBuilder

可以看到,EventBusBuilder中主要是对EventBus的一些基础的配置信息,其中的关键信息我们会在下面展开讲解。

总结一下,EventBusgetDefault()方法主要涉及的就是单例模式以及建造者模式这两种较为常见的设计模式。

register()

使用EventBus.getDefault()获取到EventBus对象之后,我们就可以向EventBus注册订阅者了,常见的注册方法如下:

 EventBus.getDefault().register(this);

我们来看一下register()方法的实现:

 /*** Registers the given subscriber to receive events. Subscribers must call {@link #unregister(Object)} once they* are no longer interested in receiving events.* <p/>* Subscribers have event handling methods that must be annotated by {@link Subscribe}.* The {@link Subscribe} annotation also allows configuration like {@link* ThreadMode} and priority.*/public void register(Object subscriber) {Class<?> subscriberClass = subscriber.getClass();List<SubscriberMethod> subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass);synchronized (this) {for (SubscriberMethod subscriberMethod : subscriberMethods) {subscribe(subscriber, subscriberMethod);}}}

可以看到,register()方法要求我们传入一个Object subscriber订阅者对象,我们一般会将Activity或者Fragmentthis传入表示将本类注册为订阅者,在register()方法中首先会调用subscriber(订阅者对象)getClass()方法获取订阅者的Class对象,然后会执行11行的subscriberMethodFinder.findSubscriberMethods(subscriberClass),从方法名我们可以看出这个方法的作用是在寻找订阅者类中的所有订阅方法,返回一个SubscriberMethodList对象。下一节我们来深入探寻一下

findSubscriberMethods(Class<?> subscriberClass)方法到的源码。

SubscriberMethodFinder.findSubscriberMethods(Class<?> subscriberClass)

源码如下:

 List<SubscriberMethod> findSubscriberMethods(Class<?> subscriberClass) {List<SubscriberMethod> subscriberMethods = METHOD_CACHE.get(subscriberClass);if (subscriberMethods != null) {return subscriberMethods;}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;}}

这里出现了一个SubscriberMethod类,我们先来看看这个类的源码:

SubscriberMethod

该类的类图如下:

可以看到,这个SubscriberMethod类主要描述的是订阅方法,即订阅者中用来订阅Event的方法,就是诸如基本用法示例中的public void receiveMessage(MessageEvent messageEvent)这类被@Subscribe注解修饰的方法。该类的主要成员变量有方法信息(method)事件类型(eventType)优先级(priority)是否粘滞(stick)等。

明确了SubscriberMethod类的内容之后我们回过头来来看看findSubscriberMethods(Class<?> subscriberClass)方法的逻辑:

class SubscriberMethodFinder {private static final Map<Class<?>, List<SubscriberMethod>> METHOD_CACHE = new ConcurrentHashMap<>();....List<SubscriberMethod> findSubscriberMethods(Class<?> subscriberClass) {List<SubscriberMethod> subscriberMethods = METHOD_CACHE.get(subscriberClass);if (subscriberMethods != null) {return subscriberMethods;}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;}}....}

可以看到,SubscriberMethodFinder类中首先有一个类型为Map<Class<?>, List<SubscriberMethod>> 的对象,其key类对象(Class)value是是SubscriberMethod对应的List集合。在findSubscriberMethods(Class<?> subscriberClass)方法中会首先从METHOD_CACHE 这个Map中根据订阅类类对象查询看是否之前已经存在该订阅者订阅方法集合了,如果已经存在(应该是之前缓存的),直接从METHOD_CACHE 这个Map中拿到对应的List并返回,如果之前没有缓存过即METHOD_CACHE 这个Map中没有以当前subscriberClasskey的键值对,则需要从subscriberClass类中去找订阅方法,关键代码即上面的12到16行代码所示:

   if (ignoreGeneratedIndex) {subscriberMethods = findUsingReflection(subscriberClass);} else {subscriberMethods = findUsingInfo(subscriberClass);}

可以看到,这里根据一个ignoreGeneratedIndex标志位值的不同执行了不同的逻辑,ignoreGeneratedIndexsubscriberMethodFinder对象的成员变量,我们寻根溯源找一下它的值:

EventBus的构造方法:

 EventBus(EventBusBuilder builder) {...subscriberMethodFinder = new SubscriberMethodFinder(builder.subscriberInfoIndexes,builder.strictMethodVerification, builder.ignoreGeneratedIndex);...}

SubscriberMethodFinder的构造方法:

SubscriberMethodFinder(List<SubscriberInfoIndex> subscriberInfoIndexes, boolean strictMethodVerification,boolean ignoreGeneratedIndex) {this.subscriberInfoIndexes = subscriberInfoIndexes;this.strictMethodVerification = strictMethodVerification;this.ignoreGeneratedIndex = ignoreGeneratedIndex;}

可以看到subscriberMethodFinder中的ignoreGeneratedIndex应该和builder.ignoreGeneratedIndex中的值是一样的,那么查看一下EventBusBuilderignoreGeneratedIndex的声明:

public class EventBusBuilder {...boolean ignoreGeneratedIndex;...}

可以看到,EventBusBuilder中只是简单对其做了声明,并未对其赋值,所以ignoreGeneratedIndex的值应该是默认的false,所以:

 if (ignoreGeneratedIndex) {subscriberMethods = findUsingReflection(subscriberClass);} else {subscriberMethods = findUsingInfo(subscriberClass);}

默认会执行:

 subscriberMethods = findUsingInfo(subscriberClass);

再往下走,我们看看findUsingInfo(subscriberClass)方法:

SubscriberMethodFinder.findUsingInfo(Class<?> subscriberClass)

源码如下:

 private List<SubscriberMethod> findUsingInfo(Class<?> subscriberClass) {FindState findState = prepareFindState();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.moveToSuperclass();}return getMethodsAndRelease(findState);}

可以看到,首先调用prepareFindState()获取了一个FindState对象,看一下prepareFindState():

SubscriberMethodFinder.prepareFindState()
 class SubscriberMethodFinder{...private static final int POOL_SIZE = 4;private static final FindState[] FIND_STATE_POOL = new FindState[POOL_SIZE];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();}}

prepareFindState()方法中首先从一个已有的FindState[] FIND_STATE_POOL对象池中找,看对象池中有没有哪一个位置是**非空(null)**的,如果有,就将该位置的值置为空(null),然后将该位置原来的对象返回,如果最后发现对象池中没有一个位置的对象值为null即对象池中不存在可用的对象,再new一个新的FindState对象并返回,这是一种经典的使用对象池达到对象复用以减少内存开销的方法,但是这和我们之前见过的对象池复用机制好像不太一样,为什么返回了原有的对象之后要将对象池原来的位置的对象值置为空?一会我们来解释,这是作者的一个巧妙设计。

我们看一下这个FindState类到底是个什么东西:

FindState

FindState类的类图如下:

首先,FindStateSubscriberMethodFinder的一个内部类,上图贴出了其成员变量及主要的方法。

那么我们回过头来继续分析这段代码:

 private List<SubscriberMethod> findUsingInfo(Class<?> subscriberClass) {FindState findState = prepareFindState();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.moveToSuperclass();}return getMethodsAndRelease(findState);}

获取了findState对象之后,执行了 findState.initForSubscriber(subscriberClass),我们看看这个方法是在干什么:

FindStat.initForSubscriber(subscriberClass)
FindState{Class<?> subscriberClass;Class<?> clazz;boolean skipSuperClasses;SubscriberInfo subscriberInfo;void initForSubscriber(Class<?> subscriberClass) {this.subscriberClass = clazz = subscriberClass;skipSuperClasses = false;subscriberInfo = null;}
}

可以看到这里主要是根据当前订阅者对象对刚才获取到的findState做了一些配置。

接下来,findUsingInfo(Class<?> 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.moveToSuperclass();}

这是一个循环,循环终止的条件是findState.clazz != null,通过FindState.initForSubscriber(Class<?> subscriberClass)方法我们可以看到findState.clazz对象当前应该是等于我们的订阅者对象subscriberClass,所以第一次会默认进入循环,然后循环中:

首先调用getSubscriberInfo(findState)

SubscriberMethodFinder.getSubscriberInfo(FindState findState)

其源码如下

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.subscriberInfo 是否为null,刚才从 findState.initForSubscriber(subscriberClass)方法中我们看到:

  subscriberInfo = null;

所以第一个if条件为false,跳过,然后判断subscriberInfoIndexes是否为null,这个subscriberInfoIndexes声明如下:

 private List<SubscriberInfoIndex> subscriberInfoIndexes;//SubscriberMethodFinder的构造方法
SubscriberMethodFinder(List<SubscriberInfoIndex> subscriberInfoIndexes, boolean strictMethodVerification,boolean ignoreGeneratedIndex) {this.subscriberInfoIndexes = subscriberInfoIndexes;this.strictMethodVerification = strictMethodVerification;this.ignoreGeneratedIndex = ignoreGeneratedIndex;}

那么我们现在就需要知道构造SubscriberMethodFinder的时候传入的List<SubscriberInfoIndex> subscriberInfoIndexes是什么。我们来看看这个subscriberMethodFinder是如何构造的:

public class EventBusBuilder {...List<SubscriberInfoIndex> subscriberInfoIndexes;boolean strictMethodVerification;boolean ignoreGeneratedIndex;...
}EventBus(EventBusBuilder builder){subscriberMethodFinder = new SubscriberMethodFinder(builder.subscriberInfoIndexes,builder.strictMethodVerification, builder.ignoreGeneratedIndex);
}

到现在就清楚了,这个subscriberInfoIndexes当前为null,所以 SubscriberMethodFinder.getSubscriberInfo(FindState findState)方法最终也会返回null,所以我们继续看这个FindStat.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.moveToSuperclass();}

根据以上分析,findState.subscriberInfo 最终为null,所以再往下走会执行 findUsingReflectionInSingleClass(findState),我们看看其源码:

SubscriberMethodFinder.findUsingReflectionInSingleClass(findState)
 private void findUsingReflectionInSingleClass(FindState findState) {Method[] methods;try {// This is faster than getMethods, especially when subscribers are fat classes like Activitiesmethods = findState.clazz.getDeclaredMethods();} catch (Throwable th) {// Workaround for java.lang.NoClassDefFoundError, see https://github.com/greenrobot/EventBus/issues/149methods = findState.clazz.getMethods();findState.skipSuperClasses = true;}for (Method method : methods) {int modifiers = method.getModifiers();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)) {String methodName = method.getDeclaringClass().getName()   "."   method.getName();throw new EventBusException("@Subscribe method "   methodName  "must have exactly 1 parameter but has "   parameterTypes.length);}} else if (strictMethodVerification && method.isAnnotationPresent(Subscribe.class)) {String methodName = method.getDeclaringClass().getName()   "."   method.getName();throw new EventBusException(methodName  " is a illegal @Subscribe method: must be public, non-static, and non-abstract");}}}

我们还是一句一句分析,首先调用methods = findState.clazz.getDeclaredMethods()findState.clazz是什么?我们来看看源码:

FindState{Class<?> subscriberClass;Class<?> clazz;boolean skipSuperClasses;SubscriberInfo subscriberInfo;void initForSubscriber(Class<?> subscriberClass) {this.subscriberClass = clazz = subscriberClass;skipSuperClasses = false;subscriberInfo = null;}
}

是的,findState.clazz就是刚才我们的订阅者对象findUsingReflectionInSingleClass()的第5行调用了它的getDeclaredMethods()方法,这个方法是java反射机制中支持的方法,主要作用是获取当前类的所有方法不包括父类和接口的,至于这个方法怎么实现的就不展开赘述了,感兴趣的读者可以自行研究java反射机制

获取到订阅者类的所有方法之后,下面使用了一个for..each循环对订阅者对象对应的订阅者类中的所有方法进行了遍历:

for (Method method : methods) {int modifiers = method.getModifiers();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)) {String methodName = method.getDeclaringClass().getName()   "."   method.getName();throw new EventBusException("@Subscribe method "   methodName  "must have exactly 1 parameter but has "   parameterTypes.length);}} else if (strictMethodVerification && method.isAnnotationPresent(Subscribe.class)) {String methodName = method.getDeclaringClass().getName()   "."   method.getName();throw new EventBusException(methodName  " is a illegal @Subscribe method: must be public, non-static, and non-abstract");}}

首先执行int modifiers = method.getModifiers(),这个getModifiers()方法是Method类提供的,作用是返回该方法的Java语言修饰符。

接下来执行了:

 if ((modifiers & Modifier.PUBLIC) != 0 && (modifiers & MODIFIERS_IGNORE) == 0)

对方法的修饰符进行了判断,我们拆开看:

(modifiers & Modifier.PUBLIC) != 0

这句意思是判断modifiers是否为Modifier.PUBLIC,如果modifiersModifier.PUBLIC的,则该条件为真。

(modifiers & MODIFIERS_IGNORE) == 0

这里的MODIFIERS_IGNORE定义如下:

private static final int BRIDGE = 0x40;
private static final int SYNTHETIC = 0x1000;
private static final int MODIFIERS_IGNORE = Modifier.ABSTRACT | Modifier.STATIC | BRIDGE | SYNTHETIC;

所以易知这一句是为了判断该方法是否是抽象方法静态方法等,如果不是,则这个条件为真,否则为假。

到这里我们就明白了,if ((modifiers & Modifier.PUBLIC) != 0 && (modifiers & MODIFIERS_IGNORE) == 0)这句是在根据方法的修饰符筛选方法,筛选出所有由public修饰的且非抽象非静态的方法,这也说明了为什么我们的订阅方法必须声明为public的。筛选出满足java修饰符要求的方法后会执行:

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)) {String methodName = method.getDeclaringClass().getName()   "."   method.getName();throw new EventBusException("@Subscribe method "   methodName  "must have exactly 1 parameter but has "   parameterTypes.length);}

这里首先通过Class<?>[] parameterTypes = method.getParameterTypes();获取到当前方法的参数类型,然后判断该方法的参数的数量是否为1,如果不是1就抛出异常,这就是为什么订阅方法必须只能指定一个参数的原因。确定了当前方法的参数长度为1之后,执行了method.getAnnotation(Subscribe.class),这个method.getAnnotation()方法的原型如下:

public <T extends Annotation> T getAnnotation(Class<T> annotationClass)

作用是判断当前方法是否存在annotationClass对应的注解,方法如果存在这样的注解,则返回指定类型的元素的注解内容,否则返回null。这里的Subscribe自然对应的就是我们配置订阅方法时使用的Subscribe注解了,其源码如下:

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface Subscribe {ThreadMode threadMode() default ThreadMode.POSTING;/*** If true, delivers the most recent sticky event (posted with* {@link EventBus#postSticky(Object)}) to this subscriber (if event available).*/boolean sticky() default false;/** Subscriber priority to influence the order of event delivery.* Within the same delivery thread ({@link ThreadMode}), higher priority subscribers will receive events before* others with a lower priority. The default priority is 0. Note: the priority does *NOT* affect the order of* delivery among subscribers with different {@link ThreadMode}s! */int priority() default 0;
}

然后执行:

  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()));}}

首先判断当前方法含有Subscribe注解,然后使用Class<?> eventType = parameterTypes[0]获取到当前方法的第一个(唯一一个)参数的类型,然后执行了findState.checkAdd(method, eventType),这个findState.checkAdd()方法是干什么的呢?

FindState.checkAdd(Method method, Class<?> eventType)

看源码:

  boolean checkAdd(Method method, Class<?> eventType) {// 2 level check: 1st level with event type only (fast), 2nd level with complete signature when required.// Usually a subscriber doesn't have methods listening to the same event type.Object existing = anyMethodByEventType.put(eventType, method);if (existing == null) {return true;} else {if (existing instanceof Method) {if (!checkAddWithMethodSignature((Method) existing, eventType)) {// Paranoia checkthrow new IllegalStateException();}// Put any non-Method object to "consume" the existing MethodanyMethodByEventType.put(eventType, this);}return checkAddWithMethodSignature(method, eventType);}}

首先执行Object existing = anyMethodByEventType.put(eventType, method),这个anyMethodByEventType的声明如下:

 static class FindState {...final Map<Class, Object> anyMethodByEventType = new HashMap<>();...}

可以看到,这个anyMethodByEventType是一个Map,存储着Class-Object的映射关系,这里调用Object existing = anyMethodByEventType.put(eventType, method),试图将<eventType(我们订阅方法中唯一一个参数的类型即事件类型),method(我们的订阅方法)> 添加到这个Map中,那么这个put的返回值应该是什么呢?根据Map.put的源码注解我们可以了解到,当anyMethodByEventType中之前存储有eventTypekey的键值对时这里返回键eventType之前对应的值,如果之前anyMethodByEventType中之前不存在以eventTypekey的键值对,则这里返回null

执行完 Object existing = anyMethodByEventType.put(eventType, method)之后会执行:

  if (existing == null) {return true;} else {if (existing instanceof Method) {if (!checkAddWithMethodSignature((Method) existing, eventType)) {// Paranoia checkthrow new IllegalStateException();}// Put any non-Method object to "consume" the existing MethodanyMethodByEventType.put(eventType, this);}return checkAddWithMethodSignature(method, eventType);}

这里首先判断existing是否为null,本质就是判断之前 anyMethodByEventType中是否存在以eventType为键的键值对,如果不存在,这里existingnull,则直接返回true,由于初始时anyMethodByEventType为空,所以existingnull,所以这里会直接返回true

如果之前存在以eventType为键的键值对,则这里的existing为之前以eventType为键的值,使用existing instanceof Method判断了一下之前键eventType对应的值是否是一个Method对象,如果是,检查了checkAddWithMethodSignature((Method) existing, eventType)的返回结果,那么这个

checkAddWithMethodSignature()是干什么的呢?

  • FindState.checkAddWithMethodSignature(Method method, Class<?> eventType)

看源码:

private boolean checkAddWithMethodSignature(Method method, Class<?> eventType) {methodKeyBuilder.setLength(0);methodKeyBuilder.append(method.getName());methodKeyBuilder.append('>').append(eventType.getName());String methodKey = methodKeyBuilder.toString();Class<?> methodClass = method.getDeclaringClass();Class<?> methodClassOld = subscriberClassByMethodKey.put(methodKey, methodClass);if (methodClassOld == null || methodClassOld.isAssignableFrom(methodClass))           {// Only add if not already found in a sub classreturn true;} else {// Revert the put, old class is further down the class hierarchysubscriberClassByMethodKey.put(methodKey, methodClassOld);return false;}}

这个方法中使用了一个methodKeyBuilder对象,我们来看看这个methodKeyBuilder对象:

 final StringBuilder methodKeyBuilder = new StringBuilder(128);

就是一个普通的StringBuilder对象,这里首先将其当前长度设为0,然后将当前方法的method.getName()追加进去,然后追加了>以及eventType.getName(),所以最终这个

methodKeyBuilder的值为:method.getName()>eventType.getName()

然后将其转化为了String存储在methodKey中,然后执行 Class<?> methodClass = method.getDeclaringClass(),这个getDeclaringClass()方法的原型如下:

public Class<T> getDeclaringClass()

这个方法的作用是返回声明此Method类的Class对象。

所以,method.getDeclaringClass()的返回值就是我们的订阅类Class对象,然后执行Class<?> methodClassOld = subscriberClassByMethodKey.put(methodKey, methodClass),再看看这个subscriberClassByMethodKey

static class FindState {final Map<String, Class> subscriberClassByMethodKey = new HashMap<>();}

也是一个Map,这里执行Class<?> methodClassOld = subscriberClassByMethodKey.put(methodKey, methodClass)之后,如果之前subscriberClassByMethodKey中存在以methodKey为键的键值对,则methodClassOldmethodKey键之前对应的值(类),否则methodClassOld的值为null

然后执行if (methodClassOld == null || methodClassOld.isAssignableFrom(methodClass))if里面两个条件,第一个methodClassOld == null就不多说了,已经解释过它何时为真。说一下methodClassOld.isAssignableFrom(methodClass)isAssignableFrom()方法是用来判断两个类的之间的关联关系,也可以说是一个类是否可以被强制转换为另外一个实例对象,具体解释:

有两个Class类型的对象,一个是调用isAssignableFrom方法的类对象(对象A),另一个是作为方法中参数的这个类对象(称之为对象B),这两个对象如果满足以下条件则返回true,否则返回false

  • A对象所对应类信息是B对象所对应的类信息的父类或者是父接口,简单理解即A是B的父类或接口
  • A对象所对应类信息与B对象所对应的类信息相同,简单理解即A和B为同一个类或同一个接口

所以,当methodClassOldmethodClass对应的是同一个类或者methodClassOldmethodClass的父类或接口时,methodClassOld.isAssignableFrom(methodClass)true,否则为false

 if (methodClassOld == null || methodClassOld.isAssignableFrom(methodClass))           {// Only add if not already found in a sub classreturn true;} else {// Revert the put, old class is further down the class hierarchysubscriberClassByMethodKey.put(methodKey, methodClassOld);return false;}}

综上,当subscriberClassByMethodKey中不存在以methodKey为键的键值对或subscriberClassByMethodKey中存在以methodKey为键的键值对,但是之前methodKey键对应的值(类)是当前类的父类,则直接返回true,相当于将当前类对象(子类)加入subscriberClassByMethodKey集合中,否则执行 subscriberClassByMethodKey.put(methodKey, methodClassOld)即将当前methodKey和其之前对应的值putsubscriberClassByMethodKey,也就是不将当前的类对象加入subscriberClassByMethodKey集合中。

那么对应到:

if (!checkAddWithMethodSignature((Method) existing, eventType)) {// Paranoia checkthrow new IllegalStateException();}

中,如果subscriberClassByMethodKey中不存在以由 existing, eventType转化的methodKey为键的键值对或subscriberClassByMethodKey中存在以methodKey为键的键值对,但是之前methodKey键对应值(类)的是当前类的父类,则这里if中的条件为假,否则说明subscriberClassByMethodKey中存在由 existing, eventType转化的methodKey为键的键值对,而且其之前对应的订阅类不是当前订阅类的父类,则抛出异常。

如果if中的条件为真,则执行:

anyMethodByEventType.put(eventType, this);

<eventType,findstate>放入anyMethodByEventType中。然后返回checkAddWithMethodSignature(method, eventType)checkAddWithMethodSignature()的源码在上面已经分析过。

好现在继续回到:

      if (findState.checkAdd(method, eventType)) {ThreadMode threadMode = subscribeAnnotation.threadMode();findState.subscriberMethods.add(new SubscriberMethod(method, eventType, threadMode,subscribeAnnotation.priority(), subscribeAnnotation.sticky()));}

我们上面提到这里第一次findState.checkAdd(method, eventType)会直接返回true,即进入到if语句块中,if语句块中首先执行 ThreadMode threadMode = subscribeAnnotation.threadMode()获取Subscribe注解中的ThreadMode属性值,通过查看Subscribe的源码发现ThreadMode默认是ThreadMode.POSTING的:

public @interface Subscribe {ThreadMode threadMode() default ThreadMode.POSTING;}

然后执行:

findState.subscriberMethods.add(new SubscriberMethod(method, eventType, threadMode,
subscribeAnnotation.priority(), subscribeAnnotation.sticky()));

findState.subscriberMethods的声明如下:

  static class FindState {final List<SubscriberMethod> subscriberMethods = new ArrayList<>();}

其是一个List,这里给subscriberMethods这个Listadd了一个新的对象:

new SubscriberMethod(method, eventType, threadMode,subscribeAnnotation.priority(), subscribeAnnotation.sticky())

SubscriberMethod构造方法的原型如下:

 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;}

对应到实例化的代码,这里使用当前订阅方法当前订阅方法的eventTye当前订阅方法对应Subscribe注解的优先级当前订阅方法对应Subscrible注解的sticky属性实例化了一个SubscriberMethod,然后将其添加到findStatesubscriberMethods中去。

然后继续看findUsingInfo()方法:

private List<SubscriberMethod> findUsingInfo(Class<?> subscriberClass) {FindState findState = prepareFindState();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.moveToSuperclass();}return getMethodsAndRelease(findState);}

刚才我们分析完了 findUsingReflectionInSingleClass(findState),其作用是将当前订阅方法添加到findState对应的List中去,然后执行 findState.moveToSuperclass()

FindState.moveToSuperclass()

我们看这个方法的源码:

void moveToSuperclass() {if (skipSuperClasses) {clazz = null;} else {clazz = clazz.getSuperclass();String clazzName = clazz.getName();/** Skip system classes, this just degrades performance. */if (clazzName.startsWith("java.") || clazzName.startsWith("javax.") || clazzName.startsWith("android.")) {clazz = null;}}}

首先判断了skipSuperClasses的值,从FindState的构造方法中:

void initForSubscriber(Class<?> subscriberClass) {this.subscriberClass = clazz = subscriberClass;skipSuperClasses = false;subscriberInfo = null;}

我们可以看到该值默认为false,那么就会执行:

clazz = clazz.getSuperclass();
String clazzName = clazz.getName();
/** Skip system classes, this just degrades performance. */
if (clazzName.startsWith("java.") || clazzName.startsWith("javax.") || clazzName.startsWith("android.")) {clazz = null;
}

首先明确clazz原本的值是什么:

 void initForSubscriber(Class<?> subscriberClass) {this.subscriberClass = clazz = subscriberClass;skipSuperClasses = false;subscriberInfo = null;}

可以看到clazz的值为initForSubscriber()中传入的参数,回想一下我们是在哪里调用initForSubscriber()的:

Class<?> subscriberClass = subscriber.getClass();
List<SubscriberMethod> subscriberMethods =subscriberMethodFinder.findSubscriberMethods(subscriberClass);
subscriberMethods = findUsingInfo(subscriberClass);
findState.initForSubscriber(subscriberClass);

所以,这个clazz就是subscriberClass,也就是我们的订阅类

继续看这段代码:

    clazz = clazz.getSuperclass();String clazzName = clazz.getName();/** Skip system classes, this just degrades performance. */if (clazzName.startsWith("java.") || clazzName.startsWith("javax.") || clazzName.startsWith("android.")) {clazz = null;}

首先使用clazz = clazz.getSuperclass()获取到当前订阅者类的父类,然后使用String clazzName = clazz.getName()获取当前订阅者类的父类的类名,然后判断:

 if (clazzName.startsWith("java.") || clazzName.startsWith("javax.") || clazzName.startsWith("android."))

就是判断了一下当前订阅者类的父类是否是以javajavaxandroid开头的,也就是判断当前类的父类是否是android本身的类,如果是,则将clazz置为null

所以这个void moveToSuperclass()方法的作用就是将findState中的clazz置为当前订阅者类的父类,当然,如果当前订阅者类没有父类或者当前订阅者类的父类是系统的类,则将clazz置为空(null)。

再继续看findUsingInfo()

private List<SubscriberMethod> findUsingInfo(Class<?> subscriberClass) {FindState findState = prepareFindState();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.moveToSuperclass();}return getMethodsAndRelease(findState);}

我们分析完了 findState.moveToSuperclass(),注意,执行完了 findState.moveToSuperclass()之后相当于第一次while循环执行完了,现在会去进行下一个while循环的判断,那么while进入循环的条件是什么?是findState.clazz != null,所以,如果之前订阅者类没有父类(或者有父类但是父类是android自身的类),则这个循环就会跳出,否则如果之前订阅者类还有父类,就会进入下一个循环,其实是一个递归的过程,从初始订阅者类开始,一级一级向上遍历父类,直到最顶级。

然后,while循环完了之后,会返回getMethodsAndRelease(findState)

SubscriberMethodFinder.getMethodsAndRelease(FindState findState);

我们看看这个方法的源码:

 private List<SubscriberMethod> getMethodsAndRelease(FindState findState) {List<SubscriberMethod> subscriberMethods = new ArrayList<>(findState.subscriberMethods);findState.recycle();synchronized (FIND_STATE_POOL) {for (int i = 0; i < POOL_SIZE; i  ) {if (FIND_STATE_POOL[i] == null) {FIND_STATE_POOL[i] = findState;break;}}}return subscriberMethods;}

这个方法首先拿到了findState.subscriberMethods,也就是订阅者中的所有订阅方法的List,注意这里是new了一个List并将findState.subscriberMethods的值拷贝了过去,而不是简单地使用=,这样做的目的是为了下一步对findState.subscriberMethods做修改时不会改变这里的subscriberMethods,也就是findState.recycle()

void recycle() {subscriberMethods.clear();anyMethodByEventType.clear();subscriberClassByMethodKey.clear();methodKeyBuilder.setLength(0);subscriberClass = null;clazz = null;skipSuperClasses = false;subscriberInfo = null;
}

可以看到,这个recycle()方法其实是将当前findState恢复成初始状态,这里使用了 subscriberMethods.clear()清空了subscriberMethods,如果之前简单使用=,则这里执行clear之后subscriberMethods也会被clear掉,这涉及到java的引用机制,这里不展开赘述。

执行findState.recycle()findState恢复初态之后,执行了:

synchronized (FIND_STATE_POOL) {for (int i = 0; i < POOL_SIZE; i  ) {if (FIND_STATE_POOL[i] == null) {FIND_STATE_POOL[i] = findState;break;}}}

这个逻辑是否有点眼熟?对的,它和前面介绍的:

class SubscriberMethodFinder{...private static final int POOL_SIZE = 4;private static final FindState[] FIND_STATE_POOL = new FindState[POOL_SIZE];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();}}

中的:

 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;}}}

逻辑是类似的,只不过prepareFindState()中是从对象池中拿出了一个findState并将其对应的位置置为null,相当于借出getMethodsAndRelease()是查看对象池中的空缺位置然后将现在不用的findState放进去,相当于归还。借出时将其坑位置为null,归还时再将坑位补上,完美地利用了内存,一点也没浪费,不得不佩服作者的神勇。

归还完findState之后 private List<SubscriberMethod> getMethodsAndRelease(FindState findState)会执行最后一行:

 return subscriberMethods;

即返回当前订阅者类的所有订阅方法。

至此,我们分析完了:

   private List<SubscriberMethod> findUsingInfo(Class<?> subscriberClass) {FindState findState = prepareFindState();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.moveToSuperclass();}return getMethodsAndRelease(findState);}

方法,记得这个方法返回的是当前订阅者类及其父类的所有订阅方法。

我们继续回退一级:

List<SubscriberMethod> findSubscriberMethods(Class<?> subscriberClass) {List<SubscriberMethod> subscriberMethods = METHOD_CACHE.get(subscriberClass);if (subscriberMethods != null) {return subscriberMethods;}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;}}

这分析完了subscriberMethods = findUsingInfo(subscriberClass)这一行,然后会判断subscriberMethods即当前订阅者类及其父类的订阅方法集合是否为空,如果为空,抛出异常,因为订阅者类中都没有订阅方法,其存在没有任何意义。如果订阅方法集合不为空,则将<当前订阅者类,当前订阅者类及其父类的所有订阅方法的集合> putMETHOD_CACHE这个Map缓存中,最后返回subscriberMethods

这时候再回退一级:

public void register(Object subscriber) {Class<?> subscriberClass = subscriber.getClass();List<SubscriberMethod> subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass);synchronized (this) {for (SubscriberMethod subscriberMethod : subscriberMethods) {subscribe(subscriber, subscriberMethod);}}}

List<SubscriberMethod> subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass);获取了当前订阅者类及其父类的所有订阅方法,然后下面使用:

synchronized (this) {for (SubscriberMethod subscriberMethod : subscriberMethods) {subscribe(subscriber, subscriberMethod);}}

即对每一个订阅方法执行了:

 subscribe(subscriber, subscriberMethod);

EventBus.subscribe(Object subscriber, SubscriberMethod subscriberMethod)

我们看看这个方法的源码:

private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) {Class<?> eventType = subscriberMethod.eventType;Subscription newSubscription = new Subscription(subscriber, subscriberMethod);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;}}List<Class<?>> subscribedEvents = typesBySubscriber.get(subscriber);if (subscribedEvents == null) {subscribedEvents = new ArrayList<>();typesBySubscriber.put(subscriber, subscribedEvents);}subscribedEvents.add(eventType);if (subscriberMethod.sticky) {if (eventInheritance) {// Existing sticky events of all subclasses of eventType have to be considered.// Note: Iterating over all events may be inefficient with lots of sticky events,// thus data structure should be changed to allow a more efficient lookup// (e.g. an additional map storing sub classes of super classes: Class -> List<Class>).Set<Map.Entry<Class<?>, Object>> entries = stickyEvents.entrySet();for (Map.Entry<Class<?>, 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);}}}

这个方法的源码有点长,我们慢慢分析。

首先,Class<?> eventType = subscriberMethod.eventType获取了当前订阅方法对应的事件类型,然后执行Subscription newSubscription = new Subscription(subscriber, subscriberMethod)实例化了一个Subscription类的对象.

Subscription

我们看看这个类的类图:

其中关注一下active这个属性:

 /*** Becomes false as soon as {@link EventBus#unregister(Object)} is called, which is checked by queued event delivery* {@link EventBus#invokeSubscriber(PendingPost)} to prevent race conditions.*/volatile boolean active;

看注释的意思是如果订阅者执行了反注册,则这个值会置为false

构造方法:

 Subscription(Object subscriber, SubscriberMethod subscriberMethod) {this.subscriber = subscriber;this.subscriberMethod = subscriberMethod;active = true;}

所以,这里是用订阅者的类对象和一个订阅方法实例化了一个Subscription类。

然后执行CopyOnWriteArrayList<Subscription> subscriptions = subscriptionsByEventType.get(eventType) , CopyOnWriteArrayListJava并发包中提供的一个并发容器,它是个线程安全且读操作无锁的ArrayList,具体实现原理不在这里展开赘述。那么这个subscriptionsByEventType是什么?

private final Map<Class<?>, CopyOnWriteArrayList<Subscription>> subscriptionsByEventType;EventBus(EventBusBuilder builder) {...subscriptionsByEventType = new HashMap<>();...}

可以看到,这个subscriptionsByEventType实际上是一个Map,初始里面什么内容都没有,所以第一次执行CopyOnWriteArrayList<Subscription> subscriptions = subscriptionsByEventType.get(eventType);一定会得的subscriptionsnull,所以下面:

  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);}}

会进入到subscriptions == null对应的代码块,即:

 subscriptions = new CopyOnWriteArrayList<>();subscriptionsByEventType.put(eventType, subscriptions);

就是先new了一个CopyOnWriteArrayList,然后将<eventType, subscriptions> putsubscriptionsByEventType中去,所以subscriptionsByEventType中存储的就是<事件类型,事件类型对应的订阅方法/订阅类的集合>这样的键值对。如果之后执行CopyOnWriteArrayList<Subscription> subscriptions = subscriptionsByEventType.get(eventType)取到的值不为null即说明之前已经有<eventType, subscriptions>putsubscriptionsByEventType里面过,就会执行:

if (subscriptions.contains(newSubscription)) {throw new EventBusException("Subscriber "   subscriber.getClass()   " already registered to event "  eventType);}

主要是判断之前eventType对应的订阅方法中是否已经存在当前的这个订阅方法,如果存在,就说明这个方法已经被注册过了,一般是由于订阅者类多次register()导致的,就抛出异常。

继续往下走,执行:

 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;}}

这里遍历了subscriptions,即遍历了与当前订阅方法对应的事件类型相同的所有订阅方法,

然后将当前订阅方法按照优先级(priority)的顺序插入到该事件类型对应的List集合中去。

然后执行:

List<Class<?>> subscribedEvents = typesBySubscriber.get(subscriber);
if (subscribedEvents == null) {subscribedEvents = new ArrayList<>();typesBySubscriber.put(subscriber, subscribedEvents);
}
subscribedEvents.add(eventType);

这里首先执行List<Class<?>> subscribedEvents = typesBySubscriber.get(subscriber),看看typesBySubscriber是什么:

private final Map<Object, List<Class<?>>> typesBySubscriber;
EventBus(EventBusBuilder builder) {...typesBySubscriber = new HashMap<>();...
}

可以看到这个typesBySubscriber也是一个Map,那么也可得出初始时subscribedEventsnull的结论,那么就会执行:

 subscribedEvents = new ArrayList<>();typesBySubscriber.put(subscriber, subscribedEvents);

这里就是将<subscriber, subscribedEvents>添加到了typesBySubscriber这个map中,所以可以知道typesBySubscriber这个map存储的就是订阅者类和订阅者类对应的所有订阅方法的事件类型集合的映射对。

然后执行subscribedEvents.add(eventType)将当前订阅方法对应的事件类型添加进去。

接下来执行:

if (subscriberMethod.sticky) {if (eventInheritance) {// Existing sticky events of all subclasses of eventType have to be considered.// Note: Iterating over all events may be inefficient with lots of sticky events,// thus data structure should be changed to allow a more efficient lookup// (e.g. an additional map storing sub classes of super classes: Class -> List<Class>).Set<Map.Entry<Class<?>, Object>> entries = stickyEvents.entrySet();for (Map.Entry<Class<?>, 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);}}

判断了一下当前订阅方法是否是sticky(粘滞)的,如果是,执行:

if (eventInheritance) {// Existing sticky events of all subclasses of eventType have to be considered.// Note: Iterating over all events may be inefficient with lots of sticky events,// thus data structure should be changed to allow a more efficient lookup// (e.g. an additional map storing sub classes of super classes: Class -> List<Class>).Set<Map.Entry<Class<?>, Object>> entries = stickyEvents.entrySet();for (Map.Entry<Class<?>, 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);}

首先判断eventInheritance的真值,这个对象是什么?它代表什么意思?

EventBus:
private final boolean eventInheritance;EventBus(EventBusBuilder builder) {eventInheritance = builder.eventInheritance;
}
EventBusBuilder:
boolean eventInheritance = true;

所以这个eventInheritance的值默认是true的,那么就会执行:

 // Existing sticky events of all subclasses of eventType have to be considered.// Note: Iterating over all events may be inefficient with lots of sticky events,// thus data structure should be changed to allow a more efficient lookup// (e.g. an additional map storing sub classes of super classes: Class -> List<Class>).
Set<Map.Entry<Class<?>, Object>> entries = stickyEvents.entrySet();
for (Map.Entry<Class<?>, Object> entry : entries) {Class<?> candidateEventType = entry.getKey();if (eventType.isAssignableFrom(candidateEventType)) {Object stickyEvent = entry.getValue();checkPostStickyEventToSubscription(newSubscription, stickyEvent);}
}

这个stickyEvents的声明如下:

private final Map<Class<?>, Object> stickyEvents;
EventBus(EventBusBuilder builder) {...stickyEvents = new ConcurrentHashMap<>();...
}

所以它就是一个线程安全的HashMapstickyEvents.entrySet()返回的是stickyEvents中所有的entry对,比如:

hash_map = new ConcurrentHashMap<Integer, String>(); // Mapping string values to int keys hash_map.put(10, "Geeks"); hash_map.put(15, "4"); hash_map.put(20, "Geeks"); hash_map.put(25, "Welcomes"); hash_map.put(30, "You"); System.out.println("The set is: "   hash_map.entrySet());

输出为:

The set is: [20=Geeks, 25=Welcomes, 10=Geeks, 30=You, 15=4]

初始时stickyEvents = new ConcurrentHashMap<>()执行完后stickyEvents一定为空,不会执行for语句里面的内容。但是我们还是简要分析一下for语句里面的代码逻辑:

for (Map.Entry<Class<?>, Object> entry : entries) {Class<?> candidateEventType = entry.getKey();if (eventType.isAssignableFrom(candidateEventType)) {Object stickyEvent = entry.getValue();checkPostStickyEventToSubscription(newSubscription, stickyEvent);}
}

这里遍历了stickyEvents中的所有entry,对每一个entry,首先通过 Class<?> candidateEventType = entry.getKey()获取到该entry对的键(key),然后判断eventType.isAssignableFrom(candidateEventType)的真值,还记得这个isAssignableFrom()的功能吗?忘记的话看这里,这个方法的作用就是判断eventType这个类对象对应的类是否是candidateEventType即当前entry对的键对应的类对象的类的父类,如果可以,执行:

 Object stickyEvent = entry.getValue();checkPostStickyEventToSubscription(newSubscription, stickyEvent);

重点是这个checkPostStickyEventToSubscription()方法:

 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, isMainThread());}}

这里对stickyEvent做了一下判空,然后调用 postToSubscription(newSubscription, stickyEvent, isMainThread()),该方法我会在讲解post()的时候详细分析

register()总结

至此,我们暂时分析完了register()的过程,总结一下其主要做了哪些工作:

  • 通过反射获取订阅者中定义的处理事件的方法集合(订阅方法集合)
  • 遍历订阅方法集合,调用subscribe方法,在这个subscribe方法内:
    • 初始化并完善subscriptionsByEventType这个map对象
    • 初始化并完善typesBySubscriber这个map对象
    • 触发stick事件的处理

看一下register()方法中逻辑的思维导图:

如果上图看不清,可下载原图查看。

post(Event event)

然后我们分析一下post()方法的执行逻辑:

 EventBus.getDefault().post(new MessageEvent("这是来自FragmentA的消息!"));

post()方法的源码如下:

 /** Posts the given event to the event bus. */public void post(Object event) {PostingThreadState postingState = currentPostingThreadState.get();List<Object> 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;}}}

首先执行了PostingThreadState postingState = currentPostingThreadState.get(),看一下这个currentPostingThreadState是什么:

 private final ThreadLocal<PostingThreadState> currentPostingThreadState = new ThreadLocal<PostingThreadState>() {@Overrideprotected PostingThreadState initialValue() {return new PostingThreadState();}};

这是一个ThreadLocal<PostingThreadState>类型的对象,主要是为每个线程存储一个唯一的PostingThreadState对象,看看PostingThreadState是什么:

    /** For ThreadLocal, much faster to set (and get multiple values). */final static class PostingThreadState {final List<Object> eventQueue = new ArrayList<>();boolean isPosting;boolean isMainThread;Subscription subscription;Object event;boolean canceled;}

里面有一个List以及一些其他的成员变量。

那么这个PostingThreadState postingState = currentPostingThreadState.get()语句做的就是获取到当前线程对应的PostingThreadState对象。

然后执行 List<Object> eventQueue = postingState.eventQueue拿到了postingState对象中的那个List,然后执行eventQueue.add(event)将当前事件添加进了eventQueue这个List中。

然后执行:

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;}}

首先判断postingState.isPosting的真值,从PostingThreadState的源码我们可以看到这个isPosting默认是false的,所以会进入if语句块内执行相应逻辑。

首先:

postingState.isMainThread = isMainThread();
postingState.isPosting = true;

postingState.isMainThreadpostingState.isPosting赋值。

然后判断postingState.canceled,从PostingThreadState源码知其默认为false,不会触发异常。然后遍历eventQueue这个List,执行了:

 postSingleEvent(eventQueue.remove(0), postingState);

EventBus.postSingleEvent(Object event, PostingThreadState postingState)

我们看看这个postSingleEvent()的源码:

private void postSingleEvent(Object event, PostingThreadState postingState) throws Error {Class<?> eventClass = event.getClass();boolean subscriptionFound = false;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) {logger.log(Level.FINE, "No subscribers registered for event "   eventClass);}if (sendNoSubscriberEvent && eventClass != NoSubscriberEvent.class &&eventClass != SubscriberExceptionEvent.class) {post(new NoSubscriberEvent(this, event));}}}

初始执行:

 Class<?> eventClass = event.getClass();boolean subscriptionFound = false;

第一句将事件event的类对象赋给eventClass,第二句将false赋给subscriptionFound

然后判断eventInheritance的真值,这个eventInheritance我们在上面分析过,其值默认为true,所以执行:

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);
}

首先执行了List<Class<?>> eventTypes = lookupAllEventTypes(eventClass),看一下lookupAllEventTypes()方法.

EventBus.lookupAllEventTypes(Class<?> eventClass)

源码:

 /** Looks up all Class objects including super classes and interfaces. Should also work for interfaces. */private static List<Class<?>> lookupAllEventTypes(Class<?> eventClass) {synchronized (eventTypesCache) {List<Class<?>> eventTypes = eventTypesCache.get(eventClass);if (eventTypes == null) {eventTypes = new ArrayList<>();Class<?> clazz = eventClass;while (clazz != null) {eventTypes.add(clazz);addInterfaces(eventTypes, clazz.getInterfaces());clazz = clazz.getSuperclass();}eventTypesCache.put(eventClass, eventTypes);}return eventTypes;}}

这里涉及到一个eventTypesCache,我们看看它的声明:

private static final Map<Class<?>, List<Class<?>>> eventTypesCache = new HashMap<>();

它是一个HashMap,这里使用了synchronized锁保证其线程安全,然后执行 List<Class<?>> eventTypes = eventTypesCache.get(eventClass),易知eventTypes应该为null,则会执行:

eventTypes = new ArrayList<>();
Class<?> clazz = eventClass;
while (clazz != null) {eventTypes.add(clazz);addInterfaces(eventTypes, clazz.getInterfaces());clazz = clazz.getSuperclass();
}
eventTypesCache.put(eventClass, eventTypes);

这里涉及到一个 addInterfaces(eventTypes, clazz.getInterfaces()):

EventBus.addInterfaces(List<Class<?>> eventTypes, Class<?>[] interfaces)

源码:

 /** Recurses through super interfaces. */static void addInterfaces(List<Class<?>> eventTypes, Class<?>[] interfaces) {for (Class<?> interfaceClass : interfaces) {if (!eventTypes.contains(interfaceClass)) {eventTypes.add(interfaceClass);addInterfaces(eventTypes, interfaceClass.getInterfaces());}}}

还是先明确调用这个方法时传入了什么参数:

  • eventTypes

    一个List,存储着事件类的类对象(eventClass)

  • interfaces

    传入了eventClass.getInterfaces(),这个getInterfaces()是一个反射方法,返回的是clazz`类实现的所有的接口的集合(数组)。

那么addInterfaces()方法执行的逻辑就很明确了:遍历当前事件类所实现的所有接口,判断这些接口是否在eventTypes这个List中,如果不在,则将该接口加入进去并递归调用,从而实现将事件者类实现的所有的祖先接口都加入到eventTypes这个List中去。

最后,执行return eventTypes将这个包含了订阅者类实现的所有接口的List集合eventTypes返回。

好,继续回到postSingleEvent()方法:

 private void postSingleEvent(Object event, PostingThreadState postingState) throws Error {Class<?> eventClass = event.getClass();boolean subscriptionFound = false;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) {logger.log(Level.FINE, "No subscribers registered for event "   eventClass);}if (sendNoSubscriberEvent && eventClass != NoSubscriberEvent.class &&eventClass != SubscriberExceptionEvent.class) {post(new NoSubscriberEvent(this, event));}}}

现在我们分析完了List<Class<?>> eventTypes = lookupAllEventTypes(eventClass)这一行,得知eventTypes代表的是当前事件类实现的所有祖先接口的集合。然后执行了:

int countTypes = eventTypes.size();
for (int h = 0; h < countTypes; h  ) {Class<?> clazz = eventTypes.get(h);subscriptionFound |= postSingleEventForEventType(event, postingState, clazz);
}

就是遍历了这个接口集合,然后对每一个接口执行:

 subscriptionFound |= postSingleEventForEventType(event, postingState, clazz);

即:

subscriptionFound =subscriptionFound | postSingleEventForEventType(event, postingState, clazz);

注意subscriptionFound是一个Boolean类型的对象,所以这句的意思是只要subscriptionFound或者 postSingleEventForEventType(event, postingState, clazz)为true,则将true赋值给subscriptionFound

我们需要分析一下postSingleEventForEventType(event, postingState, clazz)方法,看看它什么时候返回true:

EventBus.postSingleEventForEventType(Object event, PostingThreadState postingState, Class<?> eventClass)
private boolean postSingleEventForEventType(Object event, PostingThreadState postingState, Class<?> eventClass) {CopyOnWriteArrayList<Subscription> subscriptions;synchronized (this) {subscriptions = subscriptionsByEventType.get(eventClass);}if (subscriptions != null && !subscriptions.isEmpty()) {for (Subscription subscription : subscriptions) {postingState.event = event;postingState.subscription = subscription;boolean aborted = false;try {postToSubscription(subscription, event, postingState.isMainThread);aborted = postingState.canceled;} finally {postingState.event = null;postingState.subscription = null;postingState.canceled = false;}if (aborted) {break;}}return true;}return false;}

还是先明确传入的参数:

  • event

    事件对象

  • postingState

    当前线程特定的的PostingThreadState对象

  • eventClass

    当前订阅者类的某一个祖先接口的类对象

postSingleEventForEventType()方法中首先声明了一个CopyOnWriteArrayList<Subscription> subscriptions,然后在synchronized锁中执行了:

subscriptions = subscriptionsByEventType.get(eventClass);

这个subscriptionsByEventType在上面已经讨论过了,它存储的是事件类型和其对应的订阅方法&订阅类的键值对,所以subscriptions就是当前事件类型对应的订阅方法&订阅者的集合。

然后执行:

if (subscriptions != null && !subscriptions.isEmpty()) {for (Subscription subscription : subscriptions) {postingState.event = event;postingState.subscription = subscription;boolean aborted = false;try {postToSubscription(subscription, event, postingState.isMainThread);aborted = postingState.canceled;} finally {postingState.event = null;postingState.subscription = null;postingState.canceled = false;}if (aborted) {break;}}return true;
}
return false;

如果subscriptionsnull或者其中没有内容,则返回false

如果subscriptions不为空,则对其进行遍历,对每一个subscriptions中的Subscription对象,执行:

     postingState.event = event;postingState.subscription = subscription;boolean aborted = false;try {postToSubscription(subscription, event, postingState.isMainThread);aborted = postingState.canceled;} finally {postingState.event = null;postingState.subscription = null;postingState.canceled = false;}if (aborted) {break;}

前三行主要是赋值操作,然后下面执行了:

 postToSubscription(subscription, event, postingState.isMainThread);

这个方法是否有点眼熟?是的,在上面checkPostStickyEventToSubscription中曾经调用过这个方法,我说在讲解post()的时候详细解析这个方法,现在是兑现承诺的时候了。

EventBus.postToSubscription(Subscription subscription, Object event, boolean isMainThread)

源码:

 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.enqueue(subscription, event);}break;case MAIN_ORDERED:if (mainThreadPoster != null) {mainThreadPoster.enqueue(subscription, event);} else {// temporary: technically not correct as poster not decoupled from subscriberinvokeSubscriber(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);}}

首先明确传入的实参是什么:

  • subscription

    Subscription对象,主要成员变量是一个订阅方法和一个订阅者

  • event

    事件类的类对象

  • isMainThread

    表示当前订阅者是否在MainThread

然后就是一个switch语句:

switch (subscription.subscriberMethod.threadMode) {case POSTING:invokeSubscriber(subscription, event);break;case MAIN:if (isMainThread) {invokeSubscriber(subscription, event);} else {mainThreadPoster.enqueue(subscription, event);}break;case MAIN_ORDERED:if (mainThreadPoster != null) {mainThreadPoster.enqueue(subscription, event);} else {// temporary: technically not correct as poster not decoupled from subscriberinvokeSubscriber(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);
}

判断了当前订阅方法的threadMode的值,主要是按照订阅方法的线程值分为了四个主要部分处理,POSTING代表着当前线程,在哪个线程发送事件,就在哪个线程处理事件;MAIN代表只在主线程处理事件;BACKGROUND代表只在非主线程处理事件;ASYNC也是代表在非主线程处理事件。

BACKGROUNDASYNC都是在非主线程处理事件,那么二者有什么区别呢?
从代码中可以直观的看到:BACKGROUND的逻辑是如果在主线程,那么会开启一条新的线程处理事件,如果不在主线程,那么直接处理事件;而ASYNC的逻辑则是不管你处于什么线程,我都新开一条线程处理事件。

我来详细解释一下这四个不同的线程类型:

  • POSTING

    case POSTING:invokeSubscriber(subscription, event);break;
    

    这里调用了invokeSubscriber(subscription, event)

    EventBus.invokeSubscriber(Subscription subscription, Object event)

    源码如下:

     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);}}
    

    还是要明确传入的参数是什么:

    • subscription 一个Subscription对象,描述了当前事件类对象对应的订阅方法和订阅者类
    • event 当前事件对象

    subscription.subscriberMethod.method.invoke()方法的意思就是调用subscription中订阅方法的invoke()方法,传入了订阅者类和事件对象两个参数,实际上就是调用了订阅方法,并将当前事件作为参数传递进去,这样订阅方法就实现了事件的接收。

  • MAIN

    case MAIN:
    if (isMainThread) {invokeSubscriber(subscription, event);
    } else {mainThreadPoster.enqueue(subscription, event);
    }
    break;

    MAIN中首先判断当前线程是否是主线程,如果是,则直接执行invokeSubscriber,通过反射直接执行事件处理方法。反之则通过mainThreadPoster.enqueue(subscription, event)来执行事件的处理,那么它是如何切换线程的呢?我们来看一下这个mainThreadPoster的声明:

    EventBus{...private final Poster mainThreadPoster;...EventBus(EventBusBuilder builder) {...mainThreadSupport = builder.getMainThreadSupport();mainThreadPoster = mainThreadSupport != null ? mainThreadSupport.createPoster(this) : null;...}
    }

    mainThreadPoster的实例化和mainThreadSupport有关,我们来寻根溯源:

    EventBusBuilder{...MainThreadSupport getMainThreadSupport() {if (mainThreadSupport != null) {return mainThreadSupport;} else if (Logger.AndroidLogger.isAndroidLogAvailable()) {Object looperOrNull = getAndroidMainLooperOrNull();return looperOrNull == null ? null :new MainThreadSupport.AndroidHandlerMainThreadSupport((Looper) looperOrNull);} else {return null;}}...
    }
    

    这个

     Object looperOrNull = getAndroidMainLooperOrNull();
    

    从名字看就是得到Android当前的主线程的Looper,看源码:

    EventBusBuilder{...
    Object getAndroidMainLooperOrNull() {try {return Looper.getMainLooper();} catch (RuntimeException e) {// Not really a functional Android (e.g. "Stub!" maven dependencies)return null;}}...
    }
    

    getMainThreadSupport()最终返回的有效对象是:

    new MainThreadSupport.AndroidHandlerMainThreadSupport((Looper) looperOrNull);
    

    AndroidHandlerMainThreadSupport的源码如下:

    public interface MainThreadSupport {boolean isMainThread();Poster createPoster(EventBus eventBus);class AndroidHandlerMainThreadSupport implements MainThreadSupport {private final Looper looper;public AndroidHandlerMainThreadSupport(Looper looper) {this.looper = looper;}@Overridepublic boolean isMainThread() {return looper == Looper.myLooper();}@Overridepublic Poster createPoster(EventBus eventBus) {return new HandlerPoster(eventBus, looper, 10);}}}
    

    所以

     mainThreadPoster = mainThreadSupport != null ? mainThreadSupport.createPoster(this) : null;
    

    中有效的值为AndroidHandlerMainThreadSupportpublic Poster createPoster(EventBus eventBus)的返回值:new HandlerPoster(eventBus, looper, 10)看看这个HandlerPoster是什么东西.

    HandlerPoster

    源码:

    public class HandlerPoster extends Handler implements Poster {private final PendingPostQueue queue;private final int maxMillisInsideHandleMessage;private final EventBus eventBus;private boolean handlerActive;protected HandlerPoster(EventBus eventBus, Looper looper, int maxMillisInsideHandleMessage) {super(looper);this.eventBus = eventBus;this.maxMillisInsideHandleMessage = maxMillisInsideHandleMessage;queue = new PendingPostQueue();}..
    }
    

    可以看到这个HandlerPoster也就是mainThreadPoster实际上是一个主线程的Handler,因为它对应的looper是从主线程拿的。至此再看这段代码:

    case MAIN:if (isMainThread) {invokeSubscriber(subscription, event);} else {mainThreadPoster.enqueue(subscription, event);}break;

    如果当前线程不是主线程,则使用主线程中的一个Handler对象实现线程切换,那么我们深入看一下mainThreadPoster.enqueue(subscription, event)的源码:

    public class HandlerPoster extends Handler implements Poster {...public void enqueue(Subscription subscription, Object event) {PendingPost pendingPost = PendingPost.obtainPendingPost(subscription, event);synchronized (this) {queue.enqueue(pendingPost);if (!handlerActive) {handlerActive = true;if (!sendMessage(obtainMessage())) {throw new EventBusException("Could not send handler message");}}}}...}
    

    这里首先执行PendingPost pendingPost = PendingPost.obtainPendingPost(subscription, event)获取了一个PendingPost对象,我们看看这个PendingPost类:

    这个PendingPost类中有一个PendingPost next属性,应该类似于链表中的"下一个"指针。

    深入一下obtainPendingPost()方法的源码:

    static PendingPost obtainPendingPost(Subscription subscription, Object event) {synchronized (pendingPostPool) {int size = pendingPostPool.size();if (size > 0) {PendingPost pendingPost = pendingPostPool.remove(size - 1);pendingPost.event = event;pendingPost.subscription = subscription;pendingPost.next = null;return pendingPost;}}return new PendingPost(event, subscription);}

    首先使用synchronizedpendingPostPool对象进行了加锁,看一下这个pendingPostPool对象的声明:

     private final static List<PendingPost> pendingPostPool = new ArrayList<PendingPost>();
    

    它是一个List对象,然后如果该Listsize不为0,则返回该List的最后一个元素,否则就new一个PendingPost对象并返回。

    那么继续回到这段代码:

    public class HandlerPoster extends Handler implements Poster {...public void enqueue(Subscription subscription, Object event) {PendingPost pendingPost = PendingPost.obtainPendingPost(subscription, event);synchronized (this) {queue.enqueue(pendingPost);if (!handlerActive) {handlerActive = true;if (!sendMessage(obtainMessage())) {throw new EventBusException("Could not send handler message");}}}}...}
    

    获取到PendingPost之后使用synchronized锁对当前对象进行了加锁,然后将该pendingPost对象加入队列,这里再看一下和这个queue的声明:

     private final PendingPostQueue queue;
    

    再深入看看这个PendingPostQueue

    final class PendingPostQueue {private PendingPost head;private PendingPost tail;synchronized void enqueue(PendingPost pendingPost) {if (pendingPost == null) {throw new NullPointerException("null cannot be enqueued");}if (tail != null) {tail.next = pendingPost;tail = pendingPost;} else if (head == null) {head = tail = pendingPost;} else {throw new IllegalStateException("Head present, but no tail");}notifyAll();}synchronized PendingPost poll() {PendingPost pendingPost = head;if (head != null) {head = head.next;if (head == null) {tail = null;}}return pendingPost;}synchronized PendingPost poll(int maxMillisToWait) throws InterruptedException {if (head == null) {wait(maxMillisToWait);}return poll();}}

    好了,明白了,这个PendingPostQueue实际上就是作者自己写的一个双端队列,实现了入队(enqueue)和出队(poll)操作。

    所以继续看这段代码:

    public class HandlerPoster extends Handler implements Poster {...public void enqueue(Subscription subscription, Object event) {PendingPost pendingPost = PendingPost.obtainPendingPost(subscription, event);synchronized (this) {queue.enqueue(pendingPost);if (!handlerActive) {handlerActive = true;if (!sendMessage(obtainMessage())) {throw new EventBusException("Could not send handler message");}}}}...}
    

    queue.enqueue(pendingPost)就是将由当前订阅者和当前事件获取到的PendingPost对象加入到queue这个双向队列中。然后判断了一下handlerActive的真值,handlerActive的声明如下:

     private boolean handlerActive;
    

    所以其默认值为false,至于其作用我会在下面说到,这里进入if代码块内,执行:

    handlerActive = true;
    if (!sendMessage(obtainMessage())) {throw new EventBusException("Could not send handler message");
    }
    

    首先将handlerActive置为了true,然后执行sendMessage(obtainMessage())方法,并判断其返回结果,执行完sendMessage()方法之后会在本Handler类的handleMessage(Message msg)方法中收到消息,handleMessage(Message msg)源码如下:

    @Overridepublic void handleMessage(Message msg) {boolean rescheduled = false;try {long started = SystemClock.uptimeMillis();while (true) {PendingPost pendingPost = queue.poll();if (pendingPost == null) {synchronized (this) {// Check again, this time in synchronizedpendingPost = queue.poll();if (pendingPost == null) {handlerActive = false;return;}}}eventBus.invokeSubscriber(pendingPost);long timeInMethod = SystemClock.uptimeMillis() - started;if (timeInMethod >= maxMillisInsideHandleMessage) {if (!sendMessage(obtainMessage())) {throw new EventBusException("Could not send handler message");}rescheduled = true;return;}}} finally {handlerActive = rescheduled;}}
    

    首先声明了 boolean rescheduled = false,然后获取了当前时间: long started = SystemClock.uptimeMillis()

    然后是一个循环:

    while (true) {PendingPost pendingPost = queue.poll();if (pendingPost == null) {synchronized (this) {// Check again, this time in synchronizedpendingPost = queue.poll();if (pendingPost == null) {handlerActive = false;return;}}}eventBus.invokeSubscriber(pendingPost);long timeInMethod = SystemClock.uptimeMillis() - started;if (timeInMethod >= maxMillisInsideHandleMessage) {if (!sendMessage(obtainMessage())) {throw new EventBusException("Could not send handler message");}rescheduled = true;return;}}
    

    循环中,首先从队列queue中出队一个元素,然后判断其是否为null,如果不为null,则使用synchronized锁锁定当前对象,再次执行一次出队操作。我来解释一下这里为什么判断了两次queue.poll():

    解释一下:

    • 第一次判断queue.poll()是否为null
        第一次判断是在Synchronized同步代码块外进行判断,是为了在queue.poll()不为null的情况下,避免进入同步代码块,提升效率

    • 第二次判断queue.poll()是否为null
        第二次判断是为了避免以下情况的发生。
        (1)假设:线程A已经经过第一次判断,判断pendingPost == null,准备进入同步代码块.
        (2)此时线程B获得时间片,去执行enqueue()操作成功入队。
        (3)此时,线程A再次获得时间片,由于刚刚经过第一次判断pendingPost == null(不会重复判断),进入同步代码块再次判null,然后拿到不为nullpendingPost。如果不加第二次判断的话,线程A直到下一次被调用handleMessage()才有可能会处理刚才线程B加入的事件,这样不利于事件的快速传递,所以第二次判断是很有必要的。

synchronized (this) {// Check again, this time in synchronizedpendingPost = queue.poll();if (pendingPost == null) {handlerActive = false;return;}
}

这里加锁之后如果出队结果还是null,那么就说明队列中真的没有元素了,将handlerActive置为false然后return。到这里handlerActive的作用就显而易见了,其就是标记队列是否为空的,初始时队列为空,handlerActivefalse,顺利入队后队列一定不为空了,将handlerActive置为true,现在出队直到队列为空时再次将handlerActive置为false,这样仅仅通过handlerActive就可判断队列是否为空,而不用访问队列再判空。

那么如果队列出队的结果不为null,就会执行:

  eventBus.invokeSubscriber(pendingPost);long timeInMethod = SystemClock.uptimeMillis() - started;if (timeInMethod >= maxMillisInsideHandleMessage) {if (!sendMessage(obtainMessage())) {throw new EventBusException("Could not send handler message");}rescheduled = true;return;
}

首先执行eventBus.invokeSubscriber(pendingPost), invokeSubscriber方法我在上面已经解析过,作用就是执行订阅方法,将事件传递过去,这样订阅方法就能收到订阅内容了。

eventBus.invokeSubscriber(pendingPost)之后下一行计算了本方法迄今为止的耗时,如果已经超过了maxMillisInsideHandleMessage,那么调用sendMessage(obtainMessage())代表再次尝试,如果该方法返回false,则抛出异常,否则将rescheduled 置位true,并return

那么迄今为止本方法的耗时没有超过maxMillisInsideHandleMessage,则执行:

  @Overridepublic void handleMessage(Message msg) {boolean rescheduled = false;try {long started = SystemClock.uptimeMillis();while (true) {PendingPost pendingPost = queue.poll();if (pendingPost == null) {synchronized (this) {// Check again, this time in synchronizedpendingPost = queue.poll();if (pendingPost == null) {handlerActive = false;return;}}}eventBus.invokeSubscriber(pendingPost);long timeInMethod = SystemClock.uptimeMillis() - started;if (timeInMethod >= maxMillisInsideHandleMessage) {if (!sendMessage(obtainMessage())) {throw new EventBusException("Could not send handler message");}rescheduled = true;return;}}} finally {handlerActive = rescheduled;}}

最后的finally语句中还将 rescheduled赋值给了handlerActive

至于postToSubscription(Subscription subscription, Object event, boolean isMainThread)中其他几个Switch的情况和上述类似这里不做过多解释。

post(Event event总结)

好,现在我们总结一下post()方法的逻辑:

  • 将事件加入当前线程的事件队列
  • 遍历这个事件队列
    • 找到当前事件类型所有的父类事件类型,加入事件类型集合并遍历

      • 通过subscriptionsByEventType获取subscriptions集合,遍历这个subscriptions集合

        • POSTINGMAINMAIN_ORDEREDBACKGROUNDASYNC五种线程模式下通过反射执行事件处理方法

对应逻辑的思维导图如下:

如果上图看不清,可下载原图查看。

postSticky(Event event)

这里再看一下postSticky方法:

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 immediatelypost(event);}

首先用了一个锁锁住了stickyEvents,这个stickyEvents我在上面讲过:

  private final Map<Class<?>, Object> stickyEvents;EventBus(EventBusBuilder builder) {...stickyEvents = new ConcurrentHashMap<>();...}

可能有的同学会有疑问,ConcurrentHashMap它是一个线程安全的类啊,这里为什么还要对它加锁呢?是的,ConcurrentHashMap是一个线程安全的类,但是他的线程安全指的是其内部的方法是原子的、线程安全的,但是它不能保证其内部方法的复合操作也是线程安全的。也就是说它能保证put()操作是线程安全的,但是不能保证在进入postSticky()之后执行put()操作之前没有其他线程对stickyEvents执行其他操作,所以这里对stickyEvents加了一个synchronized锁。

然后将<事件对应的类型-事件>加入了该Map中,然后执行Post()方法,之后的逻辑和上面解析的post()的执行一样。

unregister(Object object)

反注册的源码如下:

 /** 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());}}

首先我们上面通过分析得知typesBySubscriber这个map存储的是订阅者类和订阅者类对应的所有订阅方法的事件类型集合的映射对,这里调用typesBySubscriber.get(subscriber)应该是获取了当前订阅者类的事件类型的类对象集合。

然后进行了判空,如果不为空,则执行:

for (Class<?> eventType : subscribedTypes) {unsubscribeByEventType(subscriber, eventType);
}
typesBySubscriber.remove(subscriber);

对所有事件类型的类对象进行遍历,依次执行 unsubscribeByEventType(subscriber, eventType),最后将本订阅类从订阅类的List中移除。

EventBus.unsubscribeByEventType(Object subscriber, Class<?> eventType)

我们深入一下 unsubscribeByEventType(subscriber, eventType)的源码:

 /** 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--;}}}}

首先从subscriptionsByEventType中拿出了所有的以eventType为事件类型类对象的订阅方法,然后对其进行遍历,如果当前方法的订阅类和当前要反注册的类相同,则将该订阅方法移除。

所以总结一下,unregister()方法的核心内容就是删除全局变量subscriptionsByEventType中所有包含当前订阅者的subscription,这也就很好的解释了为什么在解绑后我们不会再收到EventBus发送的事件了。因为发送事件的核心是根据事件类型从subscriptionsByEventType中获取subscriptions这个集合,遍历集合通过subscription可以拿到subscribersubscriberMethod,之后再通过subscription.subscriberMethod.method.invoke(subscription.subscriber, event),采用反射来进行事件的处理。unregister方法删除了全局变量subscriptionsByEventType中所有包含当前订阅者的subscription,在遍历subscriptions的时候是不会获取包含当前订阅者的subscription,所以自然不会再收到事件。

观察者模式与EventBus

其实EventBus的核心要点就是观察者模式

经典的观察者模式中,被观察者只有一个,而观察者的个数不确定。被观察者内部维持着一个观察者的集合,当被观察者要发送事件时会遍历内部的观察者集合,拿到观察者并调用观察者的相关方法。

具体到EventBus,EventBus就是一个被观察者,它的内部存放着一个subscriptionsByEventType(订阅方法)集合,这个集合包含了我们所有的观察者,也就是调用了register的所有Activity或者Fragment中的订阅方法。当使用post发送事件时,会遍历subscriptionsByEventType,拿到观察者,通过反射调用观察者中的事件处理方法。

总结

这里给出EventBus的整个思维导图:

如果上图看不清,可下载原图或源文件查看。

史上最详细最易懂的EventBus源码解析相关推荐

  1. 史上最详细的ConcurrentHashMap详解--源码分析

    ps.本文所有源码都是基于jdk1.6 首先说明一点,ConcurrentHashMap并不是可以完全替换Hashtable的,因为ConcurrentHashMap的get.clear函数是弱一致的 ...

  2. 【EventBus】EventBus 源码解析 ( 注册订阅者 | 注册订阅方法详细过程 )

    文章目录 前言 一.EventBus 注册订阅者 二.注册订阅方法的具体过程 三.Subscription 类 前言 在上一篇博客 [EventBus]EventBus 源码解析 ( 注册订阅者 | ...

  3. C语言——史上最全通讯录讲解(附源码)

    C语言--史上最全通讯录讲解(附源码) 一.开始界面的打印 二.对六大板块进行定义操作 三.对联系人进行初始化 四.对通讯录进行初始化 4.1动态版本 4.2静态版本 五.通讯录六大功能的具体实现 5 ...

  4. EventBus源码解析

    前面一篇文章讲解了EventBus的使用,但是作为开发人员,不能只停留在仅仅会用的层面上,我们还需要弄清楚它的内部实现原理.所以本篇博文将分析EventBus的源码,看看究竟它是如何实现"发 ...

  5. 【EventBus】EventBus 源码解析 ( 取消订阅 )

    文章目录 一.取消订阅 二.取消订阅 unsubscribeByEventType 方法 一.取消订阅 [EventBus]EventBus 使用示例 ( 最简单的 EventBus 示例 ) 示例中 ...

  6. EventBus 源码解析

    前言 相信大家都用过EventBus这个开源库,它基于发布/订阅模式用于组件间的沟通,解耦合避免出现回调地狱,使用起来十分简单也很好用.这样的开源库是很值得我们学习的,今天就来学习一下他的源码与设计思 ...

  7. 史上最全IO讲解,以源码角度为你剖析,颠覆你的认知!

    Java IO 是一个庞大的知识体系,很多人学着学着就会学懵了,包括我在内也是如此,所以本文将会从 Java 的 BIO 开始,一步一步深入学习,引出 JDK1.4 之后出现的 NIO 技术,对比 N ...

  8. 进击的巨人——EventBus源码解析

    "If I have seen further it is by standing on ye shoulders of Giants." -- Newton 开篇简介:巨人系列, ...

  9. 抽丝拨茧——EventBus源码解析

    一. EventBus 注册 1.EventBus.getDefault() 通过DoubleCheck创建EventBus实例 public static EventBus getDefault() ...

  10. 【EventBus】EventBus 源码解析 ( 事件发送 | postToSubscription 方法 | EventBus 线程模式处理细节 )

    文章目录 一.事件发送 postSingleEventForEventType 方法 二.事件发送 postToSubscription 方法 三.事件发送 invokeSubscriber 方法 一 ...

最新文章

  1. 设置grep高亮显示匹配项
  2. android sdcard 不存在,在android中显示sdcard上不存在的文件的提醒
  3. 关于 pip install mysqlclent安装失败 ERROR: No matching distribution found for mysqlclient 的解决方案
  4. 优秀的网工都会NAT
  5. C#3.0语法新特性集合
  6. pytorh 激活函数,循环神经网络层,损失函数和优化器
  7. Windows下安装配置SubVersion的简明步骤
  8. linux 中常用安装配置
  9. oracle 对象仕途,“事业型”凤凰男为了仕途不顾家,妻子的选择让他措手不及...
  10. Swift - 使用UIScrollView实现页面滚动切换
  11. [转]虚方法(virtual)和抽象方法(abstract)的区别
  12. 不忘初心,成于自渡——记录2020年的自己
  13. BootStrap表格详解
  14. GitLab CI/CD .gitlab-ci.yaml 关键词(三):制品artifacts,缓存cache
  15. python训练opencb分类器_垃圾邮件分类.ipynb
  16. 云课堂缺勤补签软件_GO柱状图绘图指南 | 云课堂(22)
  17. Transferable Joint Attribute-Identity Deep Learning for Unsupervised Person Re-Identification阅读总结
  18. 小程序 账本小记 统计月收入 月支出 源码分享
  19. fcfs和sjf java_《操作系统_FCFS和SJF》
  20. MDG:通过API插入MDG表数据

热门文章

  1. 北漂4年,我选择了回到家乡,我选择了父母在,不远行。
  2. 使用cecil 完毕 code injection
  3. C语言键盘各键对应的键值
  4. chrome extensions 中的交互
  5. 最保险的“跳槽理由”
  6. wifi服务器延迟高,网络延时高(网络延迟高怎么办(家里WIFI延迟高,教你几招搞定网络延迟))...
  7. SQL BETWEEN AND 用法
  8. C/C++可变参数列表参数处理方法va_list、va_start()、va_copy()、va_arg()、va_end()
  9. hilbert曲线序编码matlab,[转载]希尔伯特曲线及其matlab画法
  10. 如何搭建一个网站,访问量一天几千人如何购买服务器?...