EventBus原理总结

获取EventBus实例

1
2
3
4
5
6
7
8
9
10
11
12
public static EventBus getDefault() {
EventBus instance = defaultInstance;
if (instance == null) {
synchronized (EventBus.class) {
instance = EventBus.defaultInstance;
if (instance == null) {
instance = EventBus.defaultInstance = new EventBus();
}
}
}
return instance;
}

使用DCL双检测锁机制实现单例模式,也可以直接通过EventBus的builder()方法获取一个EventBusBuilder的实例,然后通过该建造者模式来个性化地定制自己的EventBus。

注册观察者

1
2
3
4
5
6
7
8
9
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注解的方法),并将观察者与这些方法进行订阅绑定。

  • List<SubscriberMethod> findSubscriberMethods(Class<?> subscriberClass):该方法先从缓存当中尝试获取某个观察者中的所有订阅方法,如果没有可用缓存的话就从该类中查找订阅方法,并在返回结果之前将这些方法信息放置到缓存当中。查找的过程一般是从当前观察者出发到其所有的父类,利用反射获取所有带@Subscribe注解的方法并添加到一个列表中。
  • void subscribe(Object subscriber, SubscriberMethod subscriberMethod):该方法首先将观察者与订阅方法封装成一个Subscription对象,然后从缓存中获取一个CopyOnWriteArrayList集合,它是一种适用于读多写少场景的数据结构,是一种线程安全的数组型列表,主要用来存储一个事件类型所对应的全部的Subscription对象,最后根据订阅方法的优先级插入到该列表中。该方法还从缓存中通过订阅者获取了一个事件类型列表,并将订阅方法的事件类型添加进去。

被观察者发布事件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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;
}
}
}

这里的currentPostingThreadState是一个ThreadLocal类型的变量,其中存储了对应于当前线程的PostingThreadState对象,该对象中存储了当前线程对应的事件队列和线程的状态信息等。将事件添加进事件队列中并通过循环不断取出事件队列中的事件进行发布。

void postSingleEvent(Object event, PostingThreadState postingState):根据eventInheritance的值决定是否要同时遍历当前事件的所有父类的事件信息并进行分发。如果设置为true就将执行这一操作,并最终使用postSingleEventForEventType对每个事件类型进行处理。

boolean postSingleEventForEventType(Object event, PostingThreadState postingState, Class<?> eventClass):通过事件类型从缓存中取得它对应的全部的Subscription,然后对得到的Subscription列表进行遍历,并依次调用postToSubscription方法执行事件的发布操作。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
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信息来执行不同的发布策略。

0%