
EventBus 是一个基于 发布-订阅(Publish-Subscribe)模式 的事件总线框架,广泛应用于 Android 组件间的通信。它通过解耦组件之间的依赖关系,提升代码的可维护性和灵活性。
设计模式 | 作用说明 |
|---|---|
观察者模式 | 实现事件的发布与订阅机制,核心逻辑所在 |
单例模式 | 默认提供全局唯一的 EventBus 实例 |
建造者模式 | 用于灵活配置自定义 EventBus 实例 |
策略模式 | 不同 ThreadMode 对应不同的线程调度策略 |
发布者 (Publisher) → EventBus → 订阅者 (Subscriber)
↓ ↓
post(event) @Subscribe方法// EventBus.java
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() 方法详解:private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) {
Class<?> eventType = subscriberMethod.eventType;
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("Already registered to event " + eventType);
}
}
// 按优先级插入
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;
}
}
// 记录订阅者关注的所有事件类型
List<Class<?>> subscribedEvents = typesBySubscriber.get(subscriber);
if (subscribedEvents == null) {
subscribedEvents = new ArrayList<>();
typesBySubscriber.put(subscriber, subscribedEvents);
}
subscribedEvents.add(eventType);
// 处理粘性事件
if (subscriberMethod.sticky) {
Object stickyEvent = stickyEvents.get(eventType);
if (stickyEvent != null) {
postToSubscription(newSubscription, stickyEvent,
isMainThread() && subscriberMethod.threadMode == ThreadMode.MAIN);
}
}
}关键点:
CopyOnWriteArrayList 保证并发安全。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;
try {
while (!eventQueue.isEmpty()) {
postSingleEvent(eventQueue.remove(0), postingState);
}
} finally {
postingState.isPosting = false;
postingState.isMainThread = false;
}
}
}private void postSingleEvent(Object event, PostingThreadState postingState) {
Class<?> eventClass = event.getClass();
boolean subscriptionFound = false;
if (eventInheritance) {
List<Class<?>> eventTypes = lookupAllEventTypes(eventClass);
for (Class<?> clazz : eventTypes) {
subscriptionFound |= postSingleEventForEventType(event, postingState, clazz);
}
} else {
subscriptionFound = postSingleEventForEventType(event, postingState, eventClass);
}
if (!subscriptionFound) {
if (logNoSubscriberMessages) {
Log.d(TAG, "No subscribers registered for event " + eventClass);
}
if (sendNoSubscriberEvent && eventClass != NoSubscriberEvent.class) {
post(new NoSubscriberEvent(this, event));
}
}
}特性支持:
NoSubscriberEvent 做兜底处理。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 {
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);
}
}五种线程模式:
模式 | 描述 |
|---|---|
POSTING | 在发布线程直接执行(默认) |
MAIN | 总是在主线程执行 |
MAIN_ORDERED | 主线程中有序排队执行 |
BACKGROUND | 后台线程执行(非主线程时直接调用) |
ASYNC | 异步线程池执行,不阻塞任何线程 |
List<SubscriberMethod> findSubscriberMethods(Class<?> subscriberClass) {
List<SubscriberMethod> subscriberMethods = METHOD_CACHE.get(subscriberClass);
if (subscriberMethods != null) return subscriberMethods;
if (ignoreGeneratedIndex) {
subscriberMethods = findUsingReflection(subscriberClass);
} else {
subscriberMethods = findUsingInfo(subscriberClass); // 使用编译期索引
}
METHOD_CACHE.put(subscriberClass, subscriberMethods);
return subscriberMethods;
}private List<SubscriberMethod> findUsingReflection(Class<?> subscriberClass) {
List<SubscriberMethod> subscriberMethods = new ArrayList<>();
Class<?> clazz = subscriberClass;
while (clazz != null) {
Method[] methods = clazz.getDeclaredMethods();
for (Method method : methods) {
int modifiers = method.getModifiers();
if ((modifiers & Modifier.PUBLIC) != 0 && (modifiers & MODIFIERS_IGNORE) == 0) {
Class<?>[] parameterTypes = method.getParameterTypes();
if (parameterTypes.length == 1) {
Subscribe annotation = method.getAnnotation(Subscribe.class);
if (annotation != null) {
Class<?> eventType = parameterTypes[0];
SubscriberMethod subscriberMethod = new SubscriberMethod(
method, eventType, annotation.threadMode(),
annotation.priority(), annotation.sticky()
);
subscriberMethods.add(subscriberMethod);
}
}
}
}
clazz = clazz.getSuperclass();
}
return subscriberMethods;
}优化点:
@Subscribe 方法。public class EventBus {
// 事件类型 → 所有订阅者的映射
private final Map<Class<?>, CopyOnWriteArrayList<Subscription>> subscriptionsByEventType;
// 订阅者对象 → 其订阅的所有事件类型的映射
private final Map<Object, List<Class<?>>> typesBySubscriber;
// 粘性事件缓存:事件类型 → 最新事件实例
private final Map<Class<?>, Object> stickyEvents;
// 当前线程的发布状态(ThreadLocal)
private final ThreadLocal<PostingThreadState> currentPostingThreadState;
}public class SubscriberMethod {
final Method method;
final ThreadMode threadMode;
final Class<?> eventType;
final int priority;
final boolean sticky;
}
public class Subscription {
final Object subscriber;
final SubscriberMethod subscriberMethod;
}// 避免重复反射
private static final Map<Class<?>, List<SubscriberMethod>> METHOD_CACHE =
new ConcurrentHashMap<>();
// 事件继承链缓存
private static final Map<Class<?>, List<Class<?>>> eventTypesCache = new HashMap<>();使用 APT 在编译阶段生成索引类,避免运行时反射开销。
public class MyEventBusIndex implements SubscriberInfoIndex {
private static final Map<Class<?>, SubscriberInfo> SUBSCRIBER_INDEX = new HashMap<>();
static {
putIndex(new SimpleSubscriberInfo(MainActivity.class, true,
new SubscriberMethodInfo[] {
new SubscriberMethodInfo("onMessageEvent", MessageEvent.class, ThreadMode.MAIN),
new SubscriberMethodInfo("onOtherEvent", OtherEvent.class, ThreadMode.BACKGROUND)
}));
}
}💡 优势:
final static class HandlerPoster extends Handler implements Poster {
private final PendingPostQueue queue;
public void enqueue(Subscription subscription, Object event) {
PendingPost pendingPost = PendingPost.obtainPendingPost(subscription, event);
synchronized (this) {
queue.enqueue(pendingPost);
if (!handlerActive) {
handlerActive = true;
sendMessage(obtainMessage());
}
}
}
@Override
public void handleMessage(Message msg) {
try {
long started = SystemClock.uptimeMillis();
while (true) {
PendingPost pendingPost = queue.poll();
if (pendingPost == null) break;
eventBus.invokeSubscriber(pendingPost);
// 控制单次处理时间,防止 ANR
if (SystemClock.uptimeMillis() - started > maxMillisInsideHandleMessage) {
sendMessage(obtainMessage());
return;
}
}
} finally {
handlerActive = false;
}
}
}设计亮点:
Handler 将任务投递到主线程。PendingPostQueue 缓冲待处理事件。|
@Override
protected void onDestroy() {
super.onDestroy();
EventBus.getDefault().unregister(this);
}❗未反注册会导致内存泄漏!
removeStickyEvent()。-keepattributes Signature
-keepclassmembers class * {
@org.greenrobot.eventbus.Subscribe <methods>;
}
-keep enum org.greenrobot.eventbus.ThreadMode { *; }特性 | 说明 |
|---|---|
✅ 优雅的 API 设计 | 注解驱动,register/unregister/post 三步完成通信 |
✅ 高效的线程切换 | 多种 ThreadMode 满足不同场景需求 |
✅ 性能优化充分 | 缓存 + 编译期索引大幅降低反射成本 |
✅ 支持事件继承 | 发送子类事件可通知父类订阅者 |
✅ 灵活配置能力 | 建造者模式构建自定义 EventBus 实例 |
✅ 内存安全管理 | 提供反注册机制,配合生命周期管理防泄漏 |
EventBus 通过精巧的设计,在保持简洁易用的同时,实现了强大的组件通信能力。其融合了多种经典设计模式,并结合 Android 平台特性做了深度优化,是 观察者模式在移动端的优秀实践范本。
尽管随着 Jetpack 组件(如 LiveData、Flow)的发展,部分场景下可替代 EventBus,但在跨模块通信、松耦合广播等场景中,EventBus 依然具有不可替代的价值。