一、类定义
- 为了更好的说明问题,在介绍EventBus源码以及机制之前,我们先定义两个类:
EventClass
,SubscriberClass
分别泛指用户自定义的事件类和事件的订阅者,eventObject
,subscriberObject
分别泛指订阅者和被订阅事件的实例。
EventClass
类
public class EventClass {
private String message;
public EventClass() {
}
public EventClass(String message) {
this.message = message;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
复制代码
SubscriberClass
类
public class SubscriberClass {
@Subscribe(threadMode = ThreadMode.MAIN,sticky = true)
public void onMessageEvent(EventClass eventObject) {
Log.e("MessageSubscriber", "onMessageEvent1:" + eventObject.getMessage());
}
@Subscribe(threadMode = ThreadMode.BACKGROUND, priority = 2,sticky = true)
public void onMessageEvent3(EventClass eventObject) {
Log.e("MessageSubscriber", "onMessageEvent3:" + eventObject.getMessage());
}
@Subscribe(threadMode = ThreadMode.BACKGROUND, priority = 10,sticky = true)
public void onMessageEvent4(EventClass eventObject) {
Log.e("MessageSubscriber", "onMessageEvent4:" + eventObject.getMessage());
}
@Subscribe(threadMode = ThreadMode.ASYNC, priority = 100,sticky = true)
public void onMessageEvent5(EventClass eventObject) {
Log.e("MessageSubscriber", "onMessageEvent5:" + eventObject.getMessage());
}
}
复制代码
二、使用方式:
- 订阅者注册,事件触发
1.注册订阅者:
SubscriberClass subscriberObject = new SubscriberClass();
EventBus.getDefault().register(subscriberObject);
复制代码
2.触发事件:
EventBus.getDefault().post(new EventClass("Hello World"));
复制代码
3.接收事件: 事件被post出后,就可以在subscriberObject
对象的各个参数为EventClass
方法中接收到了。可见subscriberObject
在使用方法上非常像接口对象,等待被回调。
三、EventBus类:
- 在我们了解EventBus的订阅,触发逻辑之前,我们先来了解一下
EventBus
类
EventBus类中的关键属性:
private final Map<Class<?>, CopyOnWriteArrayList<Subscription>> subscriptionsByEventType;
private final Map<Object, List<Class<?>>> typesBySubscriber;
private final Map<Class<?>, Object> stickyEvents;
private final ThreadLocal<PostingThreadState> currentPostingThreadState;
private final SubscriberMethodFinder subscriberMethodFinder;
复制代码
1.subscriptionsByEventType
-
key:eventObject的Class;value:一个线程安全的Subscription列表。 我们先来了解一下
Subscription
类:Subscription
final Object subscriber; // 注册EventBus事件接收者的对象。即我们上面定义的subscribeObject;显然一个Subscription的粒度是订阅者对象级别,而不是类级别。 final SubscriberMethod subscriberMethod; // 一个事件捕捉者的封装类对象 复制代码
SubscriberMethod
final Method method; // 捕捉事件的方法即 subcribeObject的某个参数类型为eventType的method final ThreadMode threadMode; // 从方法注解中解析出的方法的相关描述信息:线程模型 final Class<?> eventType; // 方法的参数类型,即上文定义的eventObject的参数类。 final int priority; // 事件优先级 final boolean sticky; // 是否是stickEvent String methodString; // 相当于一个方法的标签,用于比较是否相同 复制代码
由以上代码以及注释可见:
Subscription
是一个事件的执行单元。因此 EventBus的属性**subscriptionsByEventType
**的作用非常关键,当post eventObject时,会根据eventObject的类型通过 subscriptionsByEventType.get(eventObject.getClass())获取到一个Subscription,使用Subscription通过反射调用subscribeObject的相关方法,从而使订阅者接收到事件。当然具体的调用过程略复杂,我们稍后讲解。
2.typesBySubscriber
- key:观察者subscribeObject; value:subscribeObject类的所有被观察者(eventObject)的Class。 typesBySubscriber主要在unregist的过程中起作用(regist时生成和更新),unregist时,根据订阅者(subscribeObject)的类型(key),找到所有被订阅事件(eventObject)的类型List,根据事件类型在
subscriptionsByEventType
中找到所有观察者Subscriptions,如果Subscription的执行者是subscribeObject,则移除(因为显然一个Subscription是订阅者对象级别,而非类级别)。所以typesBySubscriber
只起到记录作用。
3.stickyEvents
- key:被观察者(事件)类型;value:被观察者(事件对象)。可见,相同的事件类型只会存储最近一次发送的事件。
4.currentPostingThreadState
- 场景: 存储当前线程的事件发送状况。当post一个事件,如果当前线程正在post事件则会进入post事件池,否则while循环从事件池不断取出事件,调用
postSingleEvent(Object event, PostingThreadState postingState)
方法,找到所有订阅者类名。分别调用postSingleEventForEventType(Object event, PostingThreadState postingState, Class<?> eventClass)
调用‘subscriptionsByEventType.get()’获取所有当前事件的Subscription,-
**
PostingThreadState
**类:final static class PostingThreadState { final List<Object> eventQueue = new ArrayList<>(); boolean isPosting; // 当前线程是否正在发送事件 boolean isMainThread; // 当前线程是否是MainThread Subscription subscription; // 正在发送的事件的正在发送给的订阅者; Object event; // 被观察者,事件 boolean canceled; // 事件是否被取消了,事件一般会被更高优先级的事件取消。 } 复制代码
-
5.subscriberMethodFinder
SubscriberMethodFinder
类对象 对外只提供了findSubscriberMethods方法。此类的作用是通过subscribeObject对象的类型,找到此类中所有的事件接收方法。封装成List。在EventBus类的逻辑用于生成和更新subscriptionsByEventType
和typesBySubscriber
。具体组装逻辑在后面章节讲解,此类也是EventBus2.x和EventBus3.x的主要区别。
6.标记性属性:以下EventBus中的标记性属性比较简单
private final boolean throwSubscriberException; // 在反射调用subscriberObject中的方法失败时是否抛出异常
private final boolean logSubscriberExceptions; // 在反射调用subscriberObject中的方法失败时是否打印log
private final boolean logNoSubscriberMessages; // post的eventObject无订阅者时是否打印log
private final boolean sendSubscriberExceptionEvent; // 在反射调用subscriberObject中的方法失败时是否post出SubscriberExceptionEvent事件,用户可以像订阅普通事件一样订阅SubscriberExceptionEvent
private final boolean sendNoSubscriberEvent; // post的eventObject无订阅者时是否post NoSubscriberEvent...
private final boolean eventInheritance; // post的evntObject是否触发父类对象订阅者,默认为true
private final int indexCount; // 注解生成类数量,没有实际用处。
private final Logger logger;
复制代码
7.当然还有各类事件执行器。
private final Poster mainThreadPoster; // 实际是 AndroidHandlerMainThreadSupport实例,规定了Looper为MainThreadLooper的HandlerPoster
private final BackgroundPoster backgroundPoster;
private final AsyncPoster asyncPoster;
private final ExecutorService executorService;
复制代码
根据subscribeObject--> Subscription--> SubscriberMethod--> Method 的注解,ThreadMode,分别使用不同方式在不同线程触发事件。这也是EventBus在各线程中进行穿插传递的原因。 并且AsyncPoster,BackgroundPoster,SubscriberPoster这些事件执行器都是在EventBusBuilder中初始化的Executors.newCachedThreadPool();
四、 EventBus3.0 事件机制
OK 分析完EventBus类中的基本属性之后,更详细的分析EventBus的事件机制,包括订阅者注册和事件触发两部分。
1.register源码分析:
EventBus3.0 订阅者注册的过程,实际为EventBus中的两个重要属性subscriptionsByEventType
typesBySubscriber
的组织构造过程。 EventBus3.0 之后提供了AnnnationProcessor机制,替换掉了一部分需要使用反射的地方(事件注册部分),大大提高了性能。但是在事件触发阶段依然会用到反射。