文章列表
EventBus源码解析(一)
EventBus源码解析(二)
EventBus源码解析(三)
前言
在公司项目中经常用到EventBus库,它使消息的传递变得相当简单,但是只会用是不行的,今天就来分析一下EventBus的源码。看看它到底是什么原理。
基本用法
由浅入深,还是先来看一下EventBus是怎么用的,已经把EventBus的使用方式熟读于心的小伙伴,可以忽略此部分内容。
这里只写一个最简单的用法,两个Activity之间的传值
第一个Activity:
public class ActivityA extends AppCompatActivity {
TextView textView;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_a);
textView = findViewById(R.id.text);
}
@Override
public void onStart() {
super.onStart();
//步骤1、获取实例并注册
EventBus.getDefault().register(this);;
}
@Override
public void onStop() {
super.onStop();
EventBus.getDefault().unregister(this);
}
//步骤2、编写回调
@Subscribe
public void onEvent(MessageEvent event){
if ("FromActivityB".equals(event.key) && !TextUtils.isEmpty(event.text)){
textView.setText(event.text);
}
}
public void onClick(View view){
Intent intent = new Intent(this,ActivityB.class);
startActivity(intent);
}
}
第二个Activity:
public class ActivityB extends AppCompatActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_b);
}
public void onClick(View view){
//步骤3获取实例并发送消息
EventBus.getDefault().post(new MessageEvent("FromActivityB","来自ActivityB的数据"));
}
}
很简单、提炼出步骤就是:
在接收消息的组件中:
1、获取EventBus实例并注册,即EventBus.getDefault().register(this);
2、实现消息回调方法,即自定义只有一个参数的方法并添加@Subscribe注解,及相关参数
3、取消注册EventBus.getDefault().unregister(this);
在发送消息的组件中:
1、获取实例并发送消息,即EventBus.getDefault().post(new MessageEvent("FromActivityB","来自ActivityB的数据"));
分析源码之前,先看一下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;
}
有三个参数:threadMode
、sticky
、priority
。
第一个参数ThreadMode
,可取的值有POSTING
,MAIN
,MAIN_ORDERED
,BACKGROUND
,ASYNC
,简单解释一下这几个值的意义:
POSTING
:ThreadMode
的默认取值,订阅方法会在跟事件发送在同一个线程调用;
MAIN
:订阅方法会在Android UI线程调用;
MAIN_ORDERED
:订阅方法会在Android UI线程中按顺序调用;与MAIN不同的是这个事件是非阻塞式的传递;
BACKGROUND
:在Android中,订阅方法会在后台线程调用,如果发送事件的线程不是主线程,则订阅方法的调用线程就会跟发送事件的线程是同一个;否则的话,就会在开启一个后台线程,按顺序的处理事件,订阅者需要很快的处理这个事件,防止阻塞后台线程;
ASYNC
:订阅方法总是会新开启一个线程处理事件,它不会等订阅方法执行完才发下一个消息,EventBus是使用线程池实现的这个模式;
第二个参数sticky
用来表示是否处理黏性事件、黏性事件是通过EventBus的postSticky(Object object)
方法发送的,默认值是false;
第三个参数priority
表明订阅者处理事件的优先级,同样的ThreadMode的情况下,优先级越高,会先收到发送的事件,默认的优先级是0;
分析源码
使用步骤有了,那就按着使用步骤一步一步的分析源码。
第一步:获取实例,EventBus.getDefault();
看一下getDefault()
方法是什么
public static EventBus getDefault() {
if (defaultInstance == null) {
synchronized (EventBus.class) {
if (defaultInstance == null) {
defaultInstance = new EventBus();
}
}
}
return defaultInstance;
}
public EventBus() {
this(DEFAULT_BUILDER);
}
EventBus(EventBusBuilder builder) {
logger = builder.getLogger();
subscriptionsByEventType = new HashMap<>();
typesBySubscriber = new HashMap<>();
//...省略代码...
eventInheritance = builder.eventInheritance;
executorService = builder.executorService;
}
这就是通过单例模式、来获取一个EventBus
的实例,而EventBus
的属性是通过一个Builder
提供的默认值,这些属性先按着默认值来继续往下走。
第二步:注册观察者。eventBus.register(this);
看下register(this)
方法的代码
public void register(Object subscriber) {
Class<?> subscriberClass = subscriber.getClass();
//根据传进来的类的类型,查找订阅的方法
List<SubscriberMethod> subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass);
//同步处理,循环去订阅消息
synchronized (this) {
for (SubscriberMethod subscriberMethod : subscriberMethods) {
subscribe(subscriber, subscriberMethod);
}
}
}
SubscriberMethodFinder
类用于处理查找订阅方法并且缓存订阅方法,在这里可以理解为一个“查找助手”。在上面的方法中可以看到这里又分了两步:1、查找;2、订阅;
我们分开来看
a)、查找:
List<SubscriberMethod> findSubscriberMethods(Class<?> subscriberClass) {
//在缓存中查找方法, METHOD_CACHE是一个HashMap,key为订阅者类,value为订阅者类的方法集合
List<SubscriberMethod> subscriberMethods = METHOD_CACHE.get(subscriberClass);
if (subscriberMethods != null) {
return subscriberMethods;
}
//是否忽略注解生成的SubscriberInfoIndex索引去查找=======标记一
//上面我们的用法中,没有设置EventBusBuilder的ignoreGeneratedIndex属性,所以取默认值false,会走进else分支中
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中,以便下次查找的时候,可以直接从缓存中取
METHOD_CACHE.put(subscriberClass, subscriberMethods);
return subscriberMethods;
}
}
上面的代码中注释写的很清楚,这个方法会调用else分支中的findUsingInfo(subscriberClass);
方法,接着看:
private List<SubscriberMethod> findUsingInfo(Class<?> subscriberClass) {
//获取一个FindState实例
FindState findState = prepareFindState();
//初始化参数
findState.initForSubscriber(subscriberClass);
//循环处理、循环的是向当前类的父类中继续查找
while (findState.clazz != null) {
//查找订阅者信息---注释1
findState.subscriberInfo = getSubscriberInfo(findState);
if (findState.subscriberInfo != null) {
//获取订阅者中的订阅方法的信息
SubscriberMethod[] array = findState.subscriberInfo.getSubscriberMethods();
for (SubscriberMethod subscriberMethod : array) {
//针对每个订阅方法进行"一些"检查(至于检查什么,我们后面会说)并存储在findState中的anyMethodByEventType变量中
if (findState.checkAdd(subscriberMethod.method, subscriberMethod.eventType)) {
//如果返回true,就将订阅方法存储在findState的subscriberMethods变量中
findState.subscriberMethods.add(subscriberMethod);
}
}
} else {//如果findState的subscriberInfo为null、就通过反射的方式去查找
findUsingReflectionInSingleClass(findState);
}
//处理完、需要向父类中移动,继续查找父类
findState.moveToSuperclass();
}
//释放资源并返回订阅方法集合
return getMethodsAndRelease(findState);
}
SubscriberMethodFinder
内部有一个静态内部类FindState
,此类保存了一些查找过程中用到的临时变量、并且检查订阅方法是否已经存在,并保存。
先一步一步看findUsingInfo
:
第一步,准备FindState
,先看调用的prepareFindState
方法:
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();
}
FIND_STATE_POOL
这是什么东西?
private static final int POOL_SIZE = 4;
//FindState对象池
private static final FindState[] FIND_STATE_POOL = new FindState[POOL_SIZE];
原来是从对象池中取的对象,节省资源开销;
第二步:初始化:调用FindState
类的findState.initForSubscriber(subscriberClass);
方法
void initForSubscriber(Class<?> subscriberClass) {
this.subscriberClass = clazz = subscriberClass;
skipSuperClasses = false;
subscriberInfo = null;
}
把订阅的类(即我们的ActivityA.class)赋值给findState
对象的subscriberClass
和clazz
变量,并把subscriberInfo
置为null
,这里稍微注意一下,后面要用;
第三步:进入循环,调用getSubscriberInfo(findState);
private SubscriberInfo getSubscriberInfo(FindState findState) {
//上面subscriberInfo在findState初始化的时候,被置为null,所以if中的语句不会执行,先略过、
if (findState.subscriberInfo != null && findState.subscriberInfo.getSuperSubscriberInfo() != null) {
SubscriberInfo superclassInfo = findState.subscriberInfo.getSuperSubscriberInfo();
if (findState.clazz == superclassInfo.getSubscriberClass()) {
return superclassInfo;
}
}
//subscriberInfoIndexes是通过SubscriberMethodFinder的构造方法赋值,默认的情况下这个值为null,所以if语句不执行、先略过
if (subscriberInfoIndexes != null) {
for (SubscriberInfoIndex index : subscriberInfoIndexes) {
SubscriberInfo info = index.getSubscriberInfo(findState.clazz);
if (info != null) {
return info;
}
}
}
return null;
}
看注释,也就是说这个方法返回null;findUsingInfo(Class<?> subscriberClass)
方法的注释1处,得到的返回值为null,所以会走进else逻辑,调用方法findUsingReflectionInSingleClass(findState);
;
第四步:通过反射查找,调用findUsingReflectionInSingleClass
方法
private void findUsingReflectionInSingleClass(FindState findState) {
Method[] methods;
try {
// 获取当前类中声明的方法,不包括从父类的继承的
methods = findState.clazz.getDeclaredMethods();
} catch (Throwable th) {
// Workaround for java.lang.NoClassDefFoundError, see https://github.com/greenrobot/EventBus/issues/149
methods = findState.clazz.getMethods();
findState.skipSuperClasses = true;
}
//遍历
for (Method method : methods) {
//获取方法的限定符
int modifiers = method.getModifiers();
//满足要求,public并且没有abstract、static、bridge、synthetic这些限定符
if ((modifiers & Modifier.PUBLIC) != 0 && (modifiers & MODIFIERS_IGNORE) == 0) {
//获取所有参数类型
Class<?>[] parameterTypes = method.getParameterTypes();
//过滤掉参数不为1个的方法
if (parameterTypes.length == 1) {
//获取@Subscribe注解
Subscribe subscribeAnnotation = method.getAnnotation(Subscribe.class);
//用@Subscribe注解的才能满足条件
if (subscribeAnnotation != null) {
//获取参数类型
Class<?> eventType = parameterTypes[0];
//根据参数类型存储method到findState的anyMethodByEventType变量中
if (findState.checkAdd(method, eventType)) {
//若存储成功,就继续获取注解的ThreadMode参数
ThreadMode threadMode = subscribeAnnotation.threadMode();
//至此整个过程中,此订阅方法用到的的信息都拿到了,创建SubscriberMethod对象并保存到findState.subscriberMethods变量中
findState.subscriberMethods.add(new SubscriberMethod(method, eventType, threadMode,
subscribeAnnotation.priority(), subscribeAnnotation.sticky()));
}
}
} else if (strictMethodVerification && method.isAnnotationPresent(Subscribe.class)) {
//省略异常...
} else if (strictMethodVerification && method.isAnnotationPresent(Subscribe.class)) {
//省略异常
}
}
}
这里看到有一个if(findState.checkAdd(method, eventType))
这个判断,之前在findUsingInfo
方法中也有这逻辑,但是没有走进去,但是在findUsingReflectionInSingleClass
这个方法中走进了这个逻辑,我们跟进去看看做了哪些工作
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 check
throw new IllegalStateException();
}
// Put any non-Method object to "consume" the existing Method
anyMethodByEventType.put(eventType, this);
}
return checkAddWithMethodSignature(method, eventType);
}
}
由于checkAddWithMethodSignature
方法和checkAdd
方法联系比较紧密、所以把checkAddWithMethodSignature
方法贴出来
private boolean checkAddWithMethodSignature(Method method, Class<?> eventType) {
methodKeyBuilder.setLength(0);
methodKeyBuilder.append(method.getName());
methodKeyBuilder.append('>').append(eventType.getName());
//用method名+“>”+eventType名做Key,Value为method,把映射关系存进subscriberClassByMethodKey中
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 class
return true;
} else {
// Revert the put, old class is further down the class hierarchy
subscriberClassByMethodKey.put(methodKey, methodClassOld);
return false;
}
}
第一个方法有注释,翻译一下就是:这是一个二级检查,第一级检查是快速检查,根据eventType做的检查,如果有第二级检查的话、第二级检查是根据签名来做的校验,后面还有一句:意思是一般情况下,一个订阅者不会有好几个方法同时来监听事件。来看一下是怎么做的检查
FindeState
中维护着一个Map<Class, Object>
类型的变量anyMethodByEventType
,用来存放eventType
和method
的映射关系
此方法中,先把传进来的eventType
和method
存进去,如果返回值为null证明之前anyMethodByEventType
中没有K为eventType
的值,否则的话说明已经存在一个监听此类事件的方法(通常情况不会有两个),会把任何一个非Method对象(这里是FindState对象本身)存进去“消费”掉这个已经存在的方法。并把对同一个事件监听的方法存进subscriberClassByMethodKey
变量中,其中以method的name+“>”+event的名字作为key,method作为value。
举个例子:如果一个方法中有两个(两个以上同理)方法同时对同一个事件监听,遍历这些方法分别调用checkAdd
方法,第一个方法映射关系会存进anyMethodByEventType
,当遍历到第二个方法的时候,会导致existing
不为null,进入else分支,并进行判断if (!checkAddWithMethodSignature((Method) existing, eventType))
,这个方法中会把置换出来的方法,即第一次存入anyMethodByEventType
变量中的方法,将它以签名作为key的形式存入subscriberClassByMethodKey
,而后调用anyMethodByEventType.put(eventType, this);
,将当前对象(即FindState
对象)入anyMethodByEventType
中,key为eventType
;,然后继续调用checkAddWithMethodSignature
,将第二个对当前事件监听的方法,也以签名为key的形式存入subscriberClassByMethodKey
对象中,如果此时有第三个对同一事件监听的方法进入checkAdd
方法的话,会直接走return checkAddWithMethodSignature(method, eventType);
以签名为key的形式存进subscriberClassByMethodKey
中,如果第四个呢?第四个话会和第二个的执行流程一样。读者可以自己再看一下这个逻辑。
所有的方法都执行完后,回到findUsingReflectionInSingleClass
中,findState.subscriberMethods
变量里就会把刚才遍历的所有的订阅方法加进去。至此返回到上一级方法。
到这里才只是走完findUsingInfo
方法中的else部分的逻辑,继续往下走
调用到了findState.moveToSuperclass();
void moveToSuperclass() {
//skipSuperClasses默认false
if (skipSuperClasses) {
clazz = null;
} else {
//重置clazz为其父类
clazz = clazz.getSuperclass();
String clazzName = clazz.getName();
/** 跳过系统提供的类 */
if (clazzName.startsWith("java.") || clazzName.startsWith("javax.") || clazzName.startsWith("android.")) {
clazz = null;
}
}
}
调用完moveToSuperclass
方法后,这个clazz属性就成为其父类,然后继续寻找父类中的订阅的方法,注意:父类中不用再去单独调用Event.getDefault.register(this)
。
最后还有一个释放资源的方法:
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
取到返回,并把findState
对象放回缓存池。
以上是对查找的分析,接下来开始分析订阅。
b)、订阅
public void register(Object subscriber) {
Class<?> subscriberClass = subscriber.getClass();
//根据传进来的类的类型,查找订阅的方法----查找
List<SubscriberMethod> subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass);
//同步处理,循环去订阅消息----订阅
synchronized (this) {
for (SubscriberMethod subscriberMethod : subscriberMethods) {
subscribe(subscriber, subscriberMethod);
}
}
}
循环查到的订阅方法,分别调用subscribe(subscriber, subscriberMethod);
private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) {
//获取订阅方法的监听事件的类型
Class<?> eventType = subscriberMethod.eventType;
//将订阅方法和订阅者封装到一个Subscription对象中
Subscription newSubscription = new Subscription(subscriber, subscriberMethod);
//监听相同类型的事件的由订阅方法和订阅者组成的对象存到一个list中,这个list是存储在,以事件类型为key,list为value的map中
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);
}
}
//遍历list,并根据当前订阅方法的优先级存储到list的合适的位置
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;
}
}
//typesBySubscriber用来存储一个订阅者中监听的所有类型的事件的list
List<Class<?>> subscribedEvents = typesBySubscriber.get(subscriber);
if (subscribedEvents == null) {
subscribedEvents = new ArrayList<>();
typesBySubscriber.put(subscriber, subscribedEvents);
}
//将事件类型存入事件类型list中
subscribedEvents.add(eventType);
//到此非黏性事件的注册方法就执行完了
//如果事件订阅方法支持监听黏性事件需要做如下处理
if (subscriberMethod.sticky) {
if (eventInheritance) {//事件是否需要继承,在Builder中修改这个属性,默认是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>).
//翻译一下(英语好的自行略过,翻译有误请指出):意思就是需要考虑,现有的 所有事件类型的子类 的事件。(注意断句)
//注意:遍历所有的黏性事件效率可能很低
//所以需要有一个查找效率很高数据结构
//(举例:额外用一个map来存储子类)
//翻译结束------我是分隔符-----
// stickyEvents这是个什么东西?恩看名字应该是黏性事件集合?什么时候来的?先存疑一下,看看后面会不会出现这个家伙,暂且按着字面意思理解
Set<Map.Entry<Class<?>, Object>> entries = stickyEvents.entrySet();
//遍历黏性事件
for (Map.Entry<Class<?>, Object> entry : entries) {
Class<?> candidateEventType = entry.getKey();
//做一下筛选,判断当前事件类型的类是不是与集合中某一个事件类型的类是同一个或是是其父类或接口(有点绕好好捋一捋),其实就是判断有没有继承关系,满组条件的话、执行checkPostStickyEventToSubscription方法
if (eventType.isAssignableFrom(candidateEventType)) {
Object stickyEvent = entry.getValue();
checkPostStickyEventToSubscription(newSubscription, stickyEvent);
}
}
} else {//如果忽略继承关系的话、就只针对当前时间执行checkPostStickyEventToSubscription方法
Object stickyEvent = stickyEvents.get(eventType);
checkPostStickyEventToSubscription(newSubscription, stickyEvent);
}
}
}
代码中的注释写的比较清楚,在简单捋一遍:
- 参数
subscriber
就是我们的ActivityA
; - 参数
SubscriberMethod
就是对订阅方法的一些属性的封装,包括ThreadMode
、priority
等属性、一个SubscriberMethod
标识一个订阅方法; - 局部变量
subscriptions
的类型是CopyOnWriteArrayList<Subscription>
,是用来存放监听同一个事件类型的Subscription
对象的; - 全局变量
subscriptionsByEventType
的类型是Map<Class<?>, CopyOnWriteArrayList<Subscription>>
,其中key是eventType
,value就是上面的变量subscriptions
; - 全局变量
typesBySubscriber
是Map<Object, List<Class<?>>>
类型的,其中key是订阅者对象,在这里即ActivityA,value是eventType
类型的list;
subscribe
方法的流程
方法先把subscriber
和SubscriberMethod
封装到一个Subscription
类型的对象newSubscription
中,然后从subscriptionsByEventType
中获取Subscription
的list,然后做一些初始化或者判断是否已经包含newSubscription
。
然后循环遍历subscriptions
,根据当前方法的优先级判断将newSubscription
插入到list的合适位置或者末尾。
然后根据subscriber
取出eventType
的list,如果为空初始化,并插入到typesBySubscriber
,并将当前方法监听的事件add到list中
注意:到这里所有的订阅方法的信息就会保存到subscriptionsByEventType
变量中,如果是非黏性方法,则注册的逻辑到此就走完了。下一篇文章,我们开始讲解事件的发送EventBus的post等系列方法。
如果监听方法支持黏性事件,还要多走一步逻辑
a)如果需要继承,就遍历黏性事件集合,如果是当前事件的父类就调用checkPostStickyEventToSubscription(newSubscription, stickyEvent);
;
b)如果不需要继承,就只针对当前事件调用checkPostStickyEventToSubscription(newSubscription, stickyEvent);
;
结束。
看下方法checkPostStickyEventToSubscription
的源码会发现,判断参数stickyEvent
不为空的情况下直接调用postToSubscription
,贴出postToSubscription
方法
private void postToSubscription(Subscription subscription, Object event, boolean isMainThread) {
switch (subscription.subscriberMethod.threadMode) {
case POSTING:
invokeSubscriber(subscription, event);
break;
case MAIN:
if (isMainThread) {
invokeSubscriber(subscription, event);
} else {
mainThreadPoster.enqueue(subscription, event);
}
break;
case MAIN_ORDERED:
if (mainThreadPoster != null) {
mainThreadPoster.enqueue(subscription, event);
} else {
// temporary: technically not correct as poster not decoupled from subscriber
invokeSubscriber(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
参数,对应我们监听方法的注解中的ThreadMode
的设置的值,因为我们在文章开头的例子中的ThreadMode
取的是默认值POSTING
,所以我们只看invokeSubscriber
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);
}
}
就是利用反射机制调用了invoke
方法。也就是说、如果监听事件支持黏性方法,则在监听者注册的以后,会触发监听方法回调,去处理发送过来的黏性事件。
事件的发送,我们留到EventBus源码解析(二)————EventBus事件发送。