logo头像

我有一个梦想

EventBus用法和源码解析

本文于 1320 天之前发表,文中内容可能已经过时。

[TOC]

参照版本:

EventBus 3.0以后

为什么选择EventBus

  • 简化了 组件交流方式
  • 对事件通信双方解耦
  • 灵活指定线程(4种线程模式)
  • 速度快,性能好
  • 库比较小,不占内存
  • 使用方便

使用指南

EventBus模式分工图

角色
  1. Event:事件
  2. Subscriber:事件订阅者
  3. Publisher:事件发布者
五种线程模式
  1. POSTING:默认,发布和订阅在同一个线程
  2. MAIN:事件处理函数的线程在主线程(UI)线程。不能进行耗时操作,订阅者需快速返回以免阻塞主线程
  3. MAIN_ORDERED:事件处理函数的线程在主线程(UI)线程。不能进行耗时操作,不会阻塞线程
  4. BACKGROUND:处理函数在后台线程,不能进行UI操作。发布在主线程,订阅会开启一个新的后台线程。发布在后台线程,事件处理函数也在该后台线程
  5. ASYNC:无论事件发布的线程是哪一个,都会重新开辟一个新的子线程运行,不能进行UI操作

MAIN和MAIN_ORDERED区别

  1. MAIN模式下,如果事件发布者post事件也是在主线程的话,会阻塞post事件所在的线程,意思是连续post多个事件,如果接收事件方法执行完,才能post下一个事件

post(1) ——> onReceiveMsg(1) ——>post(2)——>onReceiveMsg(2)——>post(3)——>onReceiveMsg(3)

  1. 如果事件发布者post事件不在主线程,连续post多个事件,同事在主线程是接收事件是耗时操作的话,执行的流程是非阻塞的

post(1)——>post(2)——>psot(3)——>onReceiveMsg(3)
​ 或
post(1)——>post(2)——>psot(3)——>onReceiveMsg(2)——>onReceiveMsg(3)

  1. MAIN_ORDERED模式下,无论什么场景都是非阻塞的
事件类型

普通事件:注册和反注册后,发送EventBus.post()事件,在需要接收的地方使用@Subscribe方法,方法必须是public

粘性事件:注册和反注册后,发送EventBus.postSticky()黏性事件,在需要接收的地方使用@Subscribe方法,方法必须是public,添加sticky = true

普通事件是先订阅后发送,粘性事件支持先发送后订阅

优先级

说明:优先级高的订阅者优先接收到任务

  1. threadMode参数相同
  2. 只有走到threadMode参数为POSTING的时候才会停止该事件的继续分发,调用cancelEventDelivery(xx)

混淆

1
2
3
4
5
6
7
8
9
10
-keepattributes *Annotation*
-keepclassmembers class ** {
@org.greenrobot.eventbus.Subscribe <methods>;
}
-keep enum org.greenrobot.eventbus.ThreadMode { *; }

# Only required if you use AsyncExecutor
-keepclassmembers class * extends org.greenrobot.eventbus.util.ThrowableFailureEvent {
<init>(java.lang.Throwable);
}

索引

目的:

如何使用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
android {
defaultConfig {
javaCompileOptions {
annotationProcessorOptions {
arguments = [ eventBusIndex : 'com.example.myapp.MyEventBusIndex' ] ##这里要修改为你项目的包名
}
}
}
}

dependencies {
implementation 'org.greenrobot:eventbus:3.1.1'
annotationProcessor 'org.greenrobot:eventbus-annotation-processor:3.1.1'
}

\app\build\generated\source\apt\debug\package\下可查看生成的MyEventBusIndex文件

在Application中使用

1
2
3
4
5
6
7
8
public class MyApplication extends Application {

@Override
public void onCreate() {
super.onCreate();
EventBus.builder().addIndex(new MyEventBusIndex()).installDefaultEventBus();
}
}

如果想在整个应用使用默认实例

1
2
3
EventBus.builder().addIndex(new MyEventBusIndex()).installDefaultEventBus();
// Now the default instance uses the given index. Use it like this:
EventBus eventBus = EventBus.getDefault();

源码解析

EventBus源码解析图

注册流程

1
2
3
4
5
6
7
8
9
10
11
/** 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;
}

getDefault使用单例模式,保证整个app只有唯一实例。初次进入会进入无参构造中初始化

1
2
3
4
5
6
7
/**
* 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);
}
1
private static final EventBusBuilder DEFAULT_BUILDER = new EventBusBuilder();

由此可以看出来DEFAULT_BUILDED是EventBusBuilder实例,具体的初始化在下面这个方法。

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

初始化配置,部分配置从builder中获取,这是典型的建造者模式,查看EventBusBuilder类

1
2
3
4
/** Builds an EventBus based on the current configuration. */
public EventBus build() {
return new EventBus(this);
}

查看EventBus类

1
2
3
public static EventBusBuilder builder() {
return new EventBusBuilder();
}

所以用两种初始化的方法:

  • EventBus.builder().build();
  • EventBus.getDefault()

EventBusBuilder中配置如下

  1. 成员变量
  • logSubscriberExceptions :是否打印订阅者异常信息,默认开启
  • logNoSubscriberMessages :某个事件没有订阅者时,是否打印信息,默认开启
  • sendSubscriberExceptionEvent :出现订阅者异常时,是否发送异常事件,默认开启
  • sendNoSubscriberEvent :某个事件没有订阅者时,是否发送无订阅者的事件,默认开启
  • throwSubscriberException :是否抛出订阅者异常信息,默认关闭
  • eventInheritance :事件是否可以继承形式订阅,默认开启
  • ignoreGeneratedIndex :忽略索引生成,默认关闭
  • strictMethodVerification :是否开启方法严格验证,默认关闭
  • executorService :线程池,默认是newCachedThreadPool,即没有核心线程、但最大线程数是Integer.MAX_VALUE的线程池
  • skipMethodVerificationForClasses :跳过为订阅者类里面的方法进行校验,校验包括注解信息、修饰符是否是public且非static\final的,默认为空
  • subscriberInfoIndexes :订阅者信息索引,由注解处理器生成
  • mainThreadSupport :专为Android的主线程定制,持有主线程looper引用
  1. 方法调用
  • addIndex(SubscriberInfoIndex index):添加索引

  • eventInheritance(boolean eventInheritance):是否支持事件继承

  • executorService(java.util.concurrent.ExecutorService executorService):提供用于一部和后台时间传递的自定义线程池

  • ignoreGeneratedIndex(boolean ignoreGeneratedIndex):强制使用反射,即使有生成的索引(默认值:false)。

  • skipMethodVerificationFor(java.lang.Class<?> clazz):对以onEvent开头的方法进行方法名验证,以避免键入错误;使用此方法,可以从此检查中排除订阅服务器类。

  • logNoSubscriberMessages(boolean logNoSubscriberMessages):当调用事件处理函数异常时是否打印异常信息

  • logSubscriberExceptions(boolean logSubscriberExceptions):当没有订阅者订阅该事件时是否打印日志

  • sendNoSubscriberEvent(boolean sendNoSubscriberEvent):当调用事件处理函数异常时是否发送 SubscriberExceptionEvent 事件,若此开关打开,订阅者可通过

    1
    public void onEvent(SubscriberExceptionEvent event)

    订阅该事件进行处理,默认为 true。

  • sendSubscriberExceptionEvent(boolean sendSubscriberExceptionEvent):当没有事件处理函数对事件处理时是否发送 NoSubscriberEvent 事件,若此开关打开,订阅者可通过

    1
    public void onEvent(NoSubscriberEvent event)

    订阅该事件进行处理,默认为 true。

  • strictMethodVerification**(boolean strictMethodVerification):启用严格的方法验证(默认值:false)。

  • throwSubscriberException**(boolean throwSubscriberException):如果订阅服务器引发异常,则失败(默认值:false)。

    1
    EventBus.builder().throwSubscriberException(true).installDefaultEventBus()

根据builder的默认配置统计得出:

  • 当出现订阅者异常时,打印异常log
  • 当事件没有订阅者时,打印没有订阅者log
  • 当出现订阅者异常时,发送异常事件
  • 当事件没有订阅者时,发送无订阅者事件
  • 捕获异常信息,防止崩溃
  • 事件可以继承
  • 编译时生成索引
  • 采用最大限制是Integer.MAX_VALUE的缓存线程池
  • 为每个订阅者类都进行方法校验
  • 当处于Android平台时,确保可以切换到主线程

自定义配置

1
2
3
EventBus.builder().logNoSubscriberMessages(false)
.logSubscriberExceptions(false).eventInheritance(false)...
.installDefaultEventBus();
1
2
3
EventBus.builder().logNoSubscriberMessages(false)
.logSubscriberExceptions(false).eventInheritance(false)...
.build();
1
2
3
4
5
6
7
8
9
10
public EventBus installDefaultEventBus() {
synchronized (EventBus.class) {
if (EventBus.defaultInstance != null) {
throw new EventBusException("Default instance already exists." +
" It may be only set once before it's used the first time to ensure consistent behavior.");
}
EventBus.defaultInstance = build();
return EventBus.defaultInstance;
}
}
1
2
3
public EventBus build() {
return new EventBus(this);
}

installDefaultEventBus调用的也是build()方法,但是该方法多了一个单例,确保其全局的唯一性,所以使用build方法时需要自己维护其唯一性

注册

1
EventBus.getDefault().register(this);

进入register方法

1
2
3
4
5
6
7
8
9
10
11
12
public void register(Object subscriber) {
//获取订阅者类
Class<?> subscriberClass = subscriber.getClass();
//获取该订阅类的所有订阅方法
List<SubscriberMethod> subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass);
synchronized (this) {
//挨个订阅
for (SubscriberMethod subscriberMethod : subscriberMethods) {
subscribe(subscriber, subscriberMethod);
}
}
}

SubscriberMethod是什么?

1
2
3
4
5
6
7
8
9
10
public class SubscriberMethod {
final Method method; //订阅方法
final ThreadMode threadMode; //线程模式
final Class<?> eventType; //事件类型(传递消息的对象)
final int priority; //优先级
final boolean sticky; //是否为粘性事件
/** Used for efficient comparison */
String methodString; //该并非构造初始成员变量,只是用区分其他的SubscriberMethod。
...
}

既然该事件是我们订阅方法的详细参数,那么他是从哪里来的,跟踪findSubscriberMethods

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
private static final Map<Class<?>, List<SubscriberMethod>> METHOD_CACHE = new ConcurrentHashMap<>();
......
List<SubscriberMethod> findSubscriberMethods(Class<?> subscriberClass) {
//从HashMap缓存中根据class获取对应的所有订阅方法
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;
}
}

从缓存中根据订阅者的class对象获取对应的所有订阅方法,继续跟踪subscribe()方法

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
35
36
37
38
39
40
41
private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) {
//获取订阅事件
Class<?> eventType = subscriberMethod.eventType;
Subscription newSubscription = new Subscription(subscriber, subscriberMethod);
//private final Map<Class<?>, CopyOnWriteArrayList<Subscription>> subscriptionsByEventType;
//获取该事件类型对应的所有订阅者信息(Subscription)
CopyOnWriteArrayList<Subscription> subscriptions = subscriptionsByEventType.get(eventType);
if (subscriptions == null) {
//如果信息为null,初始化subscription,将该订阅信息放入其中
subscriptions = new CopyOnWriteArrayList<>();
subscriptionsByEventType.put(eventType, subscriptions);
} else {
//如果信息不为null,map中包含该订阅信息,则报错,已经被注册了
if (subscriptions.contains(newSubscription)) {
throw new EventBusException("Subscriber " + subscriber.getClass() + " already registered to event "
+ eventType);
}
}

//根据priority优先级插入订阅信息subscriptions中
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;
}
}

// private final Map<Object, List<Class<?>>> typesBySubscriber;
//根据订阅者,从typeBySubscriber中取出订阅者事件类型
List<Class<?>> subscribedEvents = typesBySubscriber.get(subscriber);
if (subscribedEvents == null) {
//创建一个空的事件类型集和放入typesBySubscriber
subscribedEvents = new ArrayList<>();
typesBySubscriber.put(subscriber, subscribedEvents);
}
//将事件类型的class对象放入subscribedEvents
subscribedEvents.add(eventType);

.....
}
1
2
3
4
5
6
7
8
9
10
final class Subscription {
final Object subscriber;
final SubscriberMethod subscriberMethod;
/**
* 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;
...
}

Subscription为记录每个订阅方法和其对应的订阅者类,active在解注册的时候会被置为false,详看解注册

继续讲subscribe()方法

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
private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) {
...
//如果是粘性事件
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>).

//private final Map<Class<?>, Object> stickyEvents;
//stickyEvents存储具体的粘性事件
//map变化为set
Set<Map.Entry<Class<?>, Object>> entries = stickyEvents.entrySet();
//循环遍历
for (Map.Entry<Class<?>, Object> entry : entries) {
Class<?> candidateEventType = entry.getKey();
//判断candidaetEventType是否为eventType的子类
if (eventType.isAssignableFrom(candidateEventType)) {
Object stickyEvent = entry.getValue();
checkPostStickyEventToSubscription(newSubscription, stickyEvent);
}
}
} else {
Object stickyEvent = stickyEvents.get(eventType);
checkPostStickyEventToSubscription(newSubscription, stickyEvent);
}
}
}

如果是粘性事件,进入checkPostStickyEventToSubscription()方法中:

1
2
3
4
5
6
7
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());
}
}

跳转到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
35
36
37
38
39
40
41
42
private void postToSubscription(Subscription subscription, Object event, boolean isMainThread) {
//判断该事件的线程模式,执行不同操作
switch (subscription.subscriberMethod.threadMode) {
case POSTING:
invokeSubscriber(subscription, event);
break;
case MAIN:
//isMainThread判断订阅方法是否在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);
}
}

最终的enqueue()方法都是调用的invokeSubscriber方法

总结:通过注解初始化订阅方法后,在register后,在缓存中获取所有该订阅者的方法,循环遍历订阅,新建newSubscription方法,根据priority优先级将newSubscription方法放入subscriptions中,判断如果是粘性事件,则执行其对应的订阅方法。

解注册

1
EventBus.getDefault().unregister(this);

进入unregister方法

1
2
3
4
5
6
7
8
9
10
11
12
13
public synchronized void unregister(Object subscriber) {
//注册时放入的typesBySubscriber,现在从其中根据订阅者类取出订阅者事件类型
List<Class<?>> subscribedTypes = typesBySubscriber.get(subscriber);
if (subscribedTypes != null) {
//遍历执行unsubscribeByEventType,并从typesBySubscriber中删除
for (Class<?> eventType : subscribedTypes) {
unsubscribeByEventType(subscriber, eventType);
}
typesBySubscriber.remove(subscriber);
} else {
logger.log(Level.WARNING, "Subscriber to unregister was not registered before: " + subscriber.getClass());
}
}

进入unsubscribeByEventType():

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
private void unsubscribeByEventType(Object subscriber, Class<?> eventType) {
//从subscriptionsByEventType中获取所有的订阅者信息
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) {
//将active置为false,并移除
subscription.active = false;
subscriptions.remove(i);
i--;
size--;
}
}
}
}

总结:从typesBySubscriber获取订阅事件类型,根据订阅事件类型从subscriptionsByEventType获取订阅者信息,将subscription的active置为false,并移除该subscription

明显看出时regist的逆过程

typesBySubscriber :键是订阅者类,值是订阅事件类型的map

subscriptionsByEventType:键是订阅事件类型,值是订阅者信息

subscription:订阅信息,封装了订阅者类型和订阅方法,还有判断是否已经注册的active

发布普通事件

1
EventBus.getDefault().post(EventType type);

进入post:

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
public void post(Object event) {
//从线程池中获取线程
PostingThreadState postingState = currentPostingThreadState.get();
//获取线程的事件队列,并将当前事件入队
List<Object> eventQueue = postingState.eventQueue;
eventQueue.add(event);

//如果事件没有发布
if (!postingState.isPosting) {
//isMainThread()方法获取发布者当前线程
postingState.isMainThread = isMainThread();
//设置事件已发布状态
postingState.isPosting = true;
//如果事件被取消,报错
if (postingState.canceled) {
throw new EventBusException("Internal error. Abort state was not reset");
}
//轮询eventQueue发布事件,最后取消正在发布(设置为false)
try {
while (!eventQueue.isEmpty()) {
postSingleEvent(eventQueue.remove(0), postingState);
}
} finally {
postingState.isPosting = false;
postingState.isMainThread = false;
}
}
}

详看PostingThreadState是什么?

1
2
3
4
5
6
7
8
final static class PostingThreadState {
final List<Object> eventQueue = new ArrayList<>(); //object集合(队列)
boolean isPosting; //是否正在发布
boolean isMainThread; //发布者是否在主线程
Subscription subscription; //订阅信息
Object event; //当前事件
boolean canceled; //发布的事件是否被取消了
}

PostingThreadState中包含了eventQueue和其他的标志位

进入postSingleEvent:

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
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);
//是否有被订阅的,postSingleEventForEventTyper若为true,则subscriptionFound为true
subscriptionFound |= postSingleEventForEventType(event, postingState, clazz);
}
} else {
//如果事件不是被继承的
//是否有被订阅的,postSingleEventForEventTyper若为true,则subscriptionFound为true
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
post(new NoSubscriberEvent(this, event));
}
}
}

进入lookupAllEventTypes:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
private static final Map<Class<?>, List<Class<?>>> eventTypesCache = new HashMap<>();
......
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;
}
}

进入postSingleEventForEventType:

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
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;
}

进入postToSubscription中,发送事件到订阅者,根据模式不同,不同处理

总结:事件可继承,获取事件所有超类,挨个发布信息,反之则发布信息,根据不同的模式,在不同线程中做处理。

发布粘性事件

1
EventBus.getDefault().postSticky(EventType type);

进入postSticky:

1
2
3
4
5
6
7
8
9
public void postSticky(Object event) {
synchronized (stickyEvents) {
//将粘性事件放置在stickyEvents中
stickyEvents.put(event.getClass(), event);
}
// Should be posted after it is putted, in case the subscriber wants to remove immediately
//执行post方法
post(event);
}

在postSticky中将粘性事件放置在stickyEvents中,执行post事件,所以是先发送事件,

总结:在register中普通事件只是注册,而粘性事件多了一个步骤就是走了post的类似方法,在注册时会触发发布事件,这样在注册后就直接发布了。这就是粘性事件的原理。详看register源码