本文原文地址在github,不知是何原因,csdn博客显示不出来本文的图片,建议大家在github查看原文以获得最佳体验。本文全文较长,建议大家收藏,有时间的时候静下心来细细研读,同时由于笔者能力有限,文中可能存在些许问题,欢迎大家在github或csdn留言交流。
概述
EventBus
是一个基于订阅者-发布者
模式框架,该模式定义了一种一对多的依赖关系,让多个订阅者对象同时监听一个对象,通过这种方式对订阅者和主题发布者进行充分解耦,主要用于Android
组件间相互通信、线程间互相通信及其他线程与UI
线程之间互相通信等。代替了传统的Handler
、BroadCastReceiver
、Interface
回调等通信方式,相比之下EventBus
的优点是代码简洁,使用简单,并将事件发布和订阅充分解耦。
基本用法
1:添加依赖
implementation 'org.greenrobot:eventbus:3.1.1'
2:自定义一个数据类
/*** @author dmrfcoder* @date /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
的一些基础的配置信息,其中的关键信息我们会在下面展开讲解。
总结一下,EventBus
的getDefault()
方法主要涉及的就是单例模式以及建造者模式这两种较为常见的设计模式。
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
或者Fragment
的this
传入表示将本类注册为订阅者,在register()
方法中首先会调用subscriber(订阅者对象)
的getClass()
方法获取订阅者的Class对象
,然后会执行11行的subscriberMethodFinder.findSubscriberMethods(subscriberClass)
,从方法名我们可以看出这个方法的作用是在寻找订阅者类中的所有订阅方法,返回一个SubscriberMethod
的List
对象。下一节我们来深入探寻一下
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
中没有以当前subscriberClass
为key
的键值对,则需要从subscriberClass
类中去找订阅方法,关键代码即上面的12到16行代码所示:
if (ignoreGeneratedIndex) {subscriberMethods = findUsingReflection(subscriberClass);} else {subscriberMethods = findUsingInfo(subscriberClass);}
可以看到,这里根据一个ignoreGeneratedIndex
标志位值的不同执行了不同的逻辑,ignoreGeneratedIndex
是subscriberMethodFinder
对象的成员变量,我们寻根溯源找一下它的值:
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
中的值是一样的,那么查看一下EventBusBuilder
中ignoreGeneratedIndex
的声明:
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
类的类图如下:
首先,FindState
是SubscriberMethodFinder
的一个内部类,上图贴出了其成员变量及主要的方法。
那么我们回过头来继续分析这段代码:
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 /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
,如果modifiers
是Modifier.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
中之前存储有eventType
为key
的键值对时这里返回键eventType
之前对应的值,如果之前anyMethodByEventType
中之前不存在以eventType
为key
的键值对,则这里返回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
为键的键值对,如果不存在,这里existing
为null
,则直接返回true
,由于初始时anyMethodByEventType
为空,所以existing
为null
,所以这里会直接返回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
为键的键值对,则methodClassOld
为methodKey
键之前对应的值(类),否则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为同一个类或同一个接口
所以,当methodClassOld
和methodClass
对应的是同一个类或者methodClassOld
是methodClass
的父类或接口时,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
和其之前对应的值put
进subscriberClassByMethodKey
,也就是不将当前的类对象加入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
这个List
中add
了一个新的对象:
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
,然后将其添加到findState
的subscriberMethods
中去。
然后继续看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."))
就是判断了一下当前订阅者类的父类是否是以java
、javax
、android
开头的,也就是判断当前类的父类是否是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
即当前订阅者类及其父类的订阅方法集合是否为空,如果为空,抛出异常,因为订阅者类中都没有订阅方法,其存在没有任何意义。如果订阅方法集合不为空,则将<当前订阅者类,当前订阅者类及其父类的所有订阅方法的集合>
put
到METHOD_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)
,CopyOnWriteArrayList
是Java
并发包中提供的一个并发容器,它是个线程安全且读操作无锁的ArrayList
,具体实现原理不在这里展开赘述。那么这个subscriptionsByEventType
是什么?
private final Map<Class<?>, CopyOnWriteArrayList<Subscription>> subscriptionsByEventType;EventBus(EventBusBuilder builder) {...subscriptionsByEventType = new HashMap<>();...}
可以看到,这个subscriptionsByEventType
实际上是一个Map
,初始里面什么内容都没有,所以第一次执行CopyOnWriteArrayList<Subscription> subscriptions = subscriptionsByEventType.get(eventType);
一定会得的subscriptions
为null
,所以下面:
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>
put
到subscriptionsByEventType
中去,所以subscriptionsByEventType
中存储的就是<事件类型,事件类型对应的订阅方法/订阅类的集合>
这样的键值对。如果之后执行CopyOnWriteArrayList<Subscription> subscriptions = subscriptionsByEventType.get(eventType)
取到的值不为null
即说明之前已经有<eventType, subscriptions>
被put
到subscriptionsByEventType
里面过,就会执行:
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
,那么也可得出初始时subscribedEvents
为null
的结论,那么就会执行:
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<>();...}
所以它就是一个线程安全的HashMap
,stickyEvents.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.isMainThread
和postingState.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;
如果subscriptions
为null
或者其中没有内容,则返回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
也是代表在非主线程处理事件。
BACKGROUND
和ASYNC
都是在非主线程处理事件,那么二者有什么区别呢?
从代码中可以直观的看到: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;
中有效的值为AndroidHandlerMainThreadSupport
中public 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);}
首先使用synchronized
对pendingPostPool
对象进行了加锁,看一下这个pendingPostPool
对象的声明:
private final static List<PendingPost> pendingPostPool = new ArrayList<PendingPost>();
它是一个List
对象,然后如果该List
的size
不为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
,然后拿到不为null
的pendingPost
。如果不加第二次判断的话,线程A直到下一次被调用handleMessage()
才有可能会处理刚才线程B加入的事件,这样不利于事件的快速传递,所以第二次判断是很有必要的。
synchronized (this) {// Check again, this time in synchronizedpendingPost = queue.poll();if (pendingPost == null) {handlerActive = false;return;}}
这里加锁之后如果出队结果还是null
,那么就说明队列中真的没有元素了,将handlerActive
置为false
然后return
。到这里handlerActive
的作用就显而易见了,其就是标记队列是否为空的,初始时队列为空,handlerActive
为false
,顺利入队后队列一定不为空了,将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
集合 在POSTING
、MAIN
、MAIN_ORDERED
、BACKGROUND
、ASYNC
五种线程模式下通过反射执行事件处理方法
对应逻辑的思维导图如下:
如果上图看不清,可下载原图查看。
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
可以拿到subscriber
和subscriberMethod
,之后再通过subscription.subscriberMethod.method.invoke(subscription.subscriber, event)
,采用反射来进行事件的处理。unregister
方法删除了全局变量subscriptionsByEventType
中所有包含当前订阅者的subscription
,在遍历subscriptions
的时候是不会获取包含当前订阅者的subscription
,所以自然不会再收到事件。
观察者模式与EventBus
其实EventBus的核心要点就是观察者模式。
经典的观察者模式中,被观察者只有一个,而观察者的个数不确定。被观察者内部维持着一个观察者的集合,当被观察者要发送事件时会遍历内部的观察者集合,拿到观察者并调用观察者的相关方法。
具体到EventBus,EventBus就是一个被观察者,它的内部存放着一个subscriptionsByEventType(订阅方法)集合,这个集合包含了我们所有的观察者,也就是调用了register的所有Activity或者Fragment中的订阅方法。当使用post发送事件时,会遍历subscriptionsByEventType,拿到观察者,通过反射调用观察者中的事件处理方法。
总结
这里给出EventBus的整个思维导图:
如果上图看不清,可下载原图或源文件查看。