EventBus源码学习

EventBus简介

EventBus是一个Android和Java的开源库,使用发布者/订阅者模式进行松耦合。EventBus支持集中通信,只需几行代码就可以解耦类——简化代码,消除依赖关系,加快应用程序开发。(官网翻译)

EventBus架构图

  • 使用EventBus的好处:
  1. 简化了组件之间的通信
  2. 分离事件发送方和接收方
  3. 使用UI空间(Activity、Fragment…)和后台线程可以更好的通信
  4. 避免复杂且容易出错的依赖关系和生命周期的问题
  5. 快;专为高性能而优化
  6. 轻巧高效
  • 更多特性
  1. 方便的基于注解的API
  2. Android主线程交付
  3. 后台线程交付
  4. 事件和订阅者的继承关系
  5. 跳转启动
  6. 可配置

EventBus使用

首先导入依赖(不多说你懂):

compile 'org.greenrobot:eventbus:3.1.1'

1.定义事件类型

1
2
3
4
5
6
7
8
public class MessageEvent {
public final String message;
public MessageEvent(String message) {
this.message = message;
}
}

2.准备订阅者:声明并注释订阅方方法,可选择指定线程模式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// This method will be called when a MessageEvent is posted (in the UI thread for Toast)
@Subscribe(threadMode = ThreadMode.MAIN)
public void onMessageEvent(MessageEvent event) {
Toast.makeText(getActivity(), event.message, Toast.LENGTH_SHORT).show();
}
// This method will be called when a SomeOtherEvent is posted
@Subscribe
public void handleSomethingElse(SomeOtherEvent event) {
doSomethingWith(event);
@Override
public void onStart() {
super.onStart();
// 注册当前View作为观察者
EventBus.getDefault().register(this);
}
@Override
public void onStop() {
super.onStop();
// 解绑注册防止内存泄漏
EventBus.getDefault().unregister(this);
}

3.发送事件

1
EventBus.getDefault().post(new MessageEvent());

EventBus源码分析

源码的分析,我们从使用的入口进行入手。那就来看核心单例EventBus.java源码:

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
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
public class EventBus{
// 单一实例
static volatile EventBus defaultInstance;
// Builder
private static final EventBusBuilder DEFAULT_BUILDER = new EventBusBuilder();
/** 用于存储订阅者及其订阅方法集合,Key为View全类名,Value为当前订阅者的订阅方法集合*/
private final Map<Class<?>, CopyOnWriteArrayList<Subscription>> subscriptionsByEventType;
/** 当前发送者线程状态 ThreadLocal为每个线程都保存一份PostingThreadState副本 */
private final ThreadLocal<PostingThreadState> currentPostingThreadState = new ThreadLocal<PostingThreadState>() {
@Override
protected PostingThreadState initialValue() {
return new PostingThreadState();
}
};
/** 订阅者方法解析器 */
private final SubscriberMethodFinder subscriberMethodFinder;
...
/** 获取单一实例(无须解释) */
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;
}
public static EventBusBuilder builder() {
return new EventBusBuilder();
}
/** 1. 注册监听器(订阅者) */
public void register(Object subscriber) {
//获取实例类的全路径,用于后续反射
Class<?> subscriberClass = subscriber.getClass();
// 通过订阅者解析器进行订阅方法的解析
List<SubscriberMethod> subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass);
synchronized (this) {
for (SubscriberMethod subscriberMethod : subscriberMethods) {
subscribe(subscriber, subscriberMethod);
}
}
}
// 1.1 Must be called in synchronized block(必须在同步代码块中调用)
private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) {
Class<?> eventType = subscriberMethod.eventType;
// 将订阅者和其订阅方法封装为Subscription
Subscription newSubscription = new Subscription(subscriber, subscriberMethod);
// 通过全局存储的订阅者集合查询订阅方法是否已有
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);
}
}
...
}
/** 2. 发送事件 */
public void post(Object event) {
// 首先获取当前发送的线程状态
PostingThreadState postingState = currentPostingThreadState.get();
// 获取当前线程中的事件集合,并将要发送的新的事件追加到集合中
List<Object> eventQueue = postingState.eventQueue;
eventQueue.add(event);
// 如果当前任务中没有正在发送的事件
if (!postingState.isPosting) {
// 当前发送线程是否为主线程
postingState.isMainThread = isMainThread();
// 将正在发送标记置位true准备发送数据
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;
}
}
}
/** 2.1 发送单个事件 */
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);
subscriptionFound |= postSingleEventForEventType(event, postingState, clazz);
}
} else {
// 发送当前单个事件
subscriptionFound = postSingleEventForEventType(event, postingState, eventClass);
}
// 如果接收该事件的订阅者未找到,则发送一个NoSubscriberEvent的事件
if (!subscriptionFound) {
if (logNoSubscriberMessages) {
logger.log(Level.FINE, "No subscribers registered for event " + eventClass);
}
if (sendNoSubscriberEvent && eventClass != NoSubscriberEvent.class &&
eventClass != SubscriberExceptionEvent.class) {
post(new NoSubscriberEvent(this, event));
}
}
}
/** 2.2 发送单个事件根据事件类型 该方法做了两件事:1. 发送事件;2. 返回是否有即将发送事件的接收者*/
private boolean postSingleEventForEventType(Object event, PostingThreadState postingState, Class<?> eventClass) {
...
// 发送事件
postToSubscription(subscription, event, postingState.isMainThread);
...
return true | false;
}
// 2.3 按照线程模式进行事件发送
private void postToSubscription(Subscription subscription, Object event, boolean isMainThread) {
switch (subscription.subscriberMethod.threadMode) {
case POSTING:
// 默认线程模式:要求发送和订阅操作在同一线程进行,效率最快,避免了线程切换
invokeSubscriber(subscription, event);
break;
case MAIN:
// 主线程模式:该模式代表订阅者在主线程,一般使用该方式说明发送者应该在子线程操作,否则和POSTING一样
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:
// 后台线程模式:该方式代表订阅者在子线程,如果发送者在子线程,则发送和订阅应在同一子线程;如果发送者在主线程,则EventBus会给该模式的订阅者创建一个独立的子线程来执行订阅方法。
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);
}
}
/** 2.4 通过发射从订阅者中找到接收该事件类型的方法进行回调 */
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);
}
}
/** For ThreadLocal, much faster to set (and get multiple values). */
final static class PostingThreadState {
final List<Object> eventQueue = new ArrayList<>();
boolean isPosting;
boolean isMainThread;
Subscription subscription;
Object event;
boolean canceled;
}
/** 3. 防止内存泄漏取消注册 */
public synchronized void unregister(Object subscriber) {
List<Class<?>> subscribedTypes = typesBySubscriber.get(subscriber);
if (subscribedTypes != null) {
for (Class<?> eventType : subscribedTypes) {
unsubscribeByEventType(subscriber, eventType);
}
typesBySubscriber.remove(subscriber);
} else {
logger.log(Level.WARNING, "Subscriber to unregister was not registered before: " + subscriber.getClass());
}
}
...
}

总结

EventBus使用观察者模式,它的原理可以简单的理解为:

  1. 在对应视图V中进行register()作为观察者,EventBus对该实例进行存储;
  2. 在对应视图V中进行接收事件方法的逻辑处理并使用@Subscribe进行注解;
  3. EventBus在发送事件时,通过存储的观察者实例以及使用annotationProcessor注解解析器对@Subscribe注解的解析,最后利用反射调用对应方法将事件数据回传;
如果帮到了你,想打赏支持,喏~