虽然我在这里写下Eventbus,但是,还是觉得老司机教你 “飙” EventBus 3 才是很完美的文章。
1. 前言
EventBus是平常开发中很常用的框架,用了简直爱不释手。在这里,以Eventbus3.0 为例,来了解一下。首先了解点简单的用法。
- gradle文件中引入
compile 'org.greenrobot:eventbus:3.0.0'
- 注册与解注
//注册
EventBus.getDefault().register(this);
//解注
EventBus.getDefault().unregister(this);
- 在需要接收事件的地方使用@Subscribe 注解方法,例如:
@Subscribe(threadMode = ThreadMode.MAIN)
public void onEvent(Object event) {
}
2. 从register开始
该方法中,有两个重要步骤。
- 找到订阅方法,也就是@Subscribe 注解的方法
- 进行订阅
3. SubscriberMethodFinder#findSubscriberMethods
上面的代码步骤如下:
- 先从cache中查找
- 如果有,返回
- 如果没有,继续
- 如果没开始索引(后面会说道)
- findUsingReflection 通过反射方法获取订阅方法
- 开启了索引
- findUsingInfo 通过索引获取
- 将查找到的订阅方法,放入cache,并返回
4.SubscriberMethodFinder#findUsingReflection
- prepareFindState,将FIND_STATE_POOL内元素置null,返回一个新的FindState。
- 当findState.clazz 不为null的时候,调用findUsingReflectionInSingleClass和moveToSuperclass方法,
- getMethodsAndRelease(findState) 返回订阅列表。
下面,我们来了解下FindState的这几个方法。
5.FindState#findUsingReflectionInSingleClass 和moveToSuperclass方法。
看下findUsingReflectionInSingleClass的相关代码。
- 获取类的所有方法,如果出异常的话就获取类的所有public方法,并将skipSuperClasses设置true
- 遍历所有methods
- 获取方法的修饰符
- 如果是public,并且不是ABSTRACT,STATIC,VOLATILE,SYNTHETIC的话
- 获取方法参数类型和需要的一些参数,加到subscriberMethods中,其余情况则抛出异常
- 获取方法的修饰符
从代码中可以看出,SubscriberMethod包含以下几个参数
- 方法名
- 事件类型(接收什么事件对象)
- threadModel
- 优先级
- 是否是粘性事件
moveToSuperclass 方法就简单了。
在允许的情况下,将clazz对象置为当前clazz的父类,这样,整个查询方法就完成了。到这里,查到了register类中及其父类中,所有的订阅方法。
6. EventBus#subscribe
该方法的逻辑步骤如下:
- new Subscription,这个类维护了订阅类与其一个订阅方法
- 从subscriptionsByEventType列表中,查找是否有与当前订阅方法参数相同(eventType)的集合
- 如果没有,创建并加入
- 如果有,但是已经含有当前方法,抛出只能订阅一次的方法
- 循环,如果当前eventType的列表中的,该事件的优先级高,则插入(优先级排序),否则,在列表末尾加入
- 从typesBySubscriber中获取当前订阅者的所有方法,如果为null,创建并插入数据
- 如果当前订阅事件为粘性事件,并根据是否支持事件继承来做一些判断
- checkPostStickyEventToSubscription方法,传入了我们从stickyEvents拿出的事件
到这里我们就完成了订阅的全部过程。不过,粘性事件可还没完,当注册了粘性事件之后,我们就会接受到以前发送的粘性事件。我们接着看checkPostStickyEventToSubscription,这个方法只是对参数进行checkNull,随后交给postToSubscription方法处理了。
7.EVentBus#postToSubscription
这里的Event就是我们从stickyEvents拿出来的事件,这个会根据ThreadMode去选择是直接反射调用方法,还是将事件插入队列。我们一一看下。
可以看到,invokeSubscriber方法,直接反射调用我们的订阅方法来发送事件。我们在来看另外一种,另外一种利用HandlerPoster#enqueue方法,插入事件,在HandlerPoster#handleMessage方法中,会调用EventBus的invokeSubscriber方法,如下
哈,到这里,整个完整的订阅流程结束了。