EventBus 是 Android 領域最流行的事件總線框架,通過發布-訂閱模式解耦組件通信。本文基於源碼(含中文註釋版),從構造器、註冊、發布、線程調度四個維度深度剖析其核心機制。
| 術語 | 說明 |
|---|---|
| Event(事件) | 任意對象,作為消息載體;事件類型即其 Class |
| Subscriber(訂閱者) | 註冊接收特定事件類型的對象,含優先級,可取消傳遞 |
| Publisher(發布者) | 調用 EventBus.getDefault().post(event) 發送事件 |
| ThreadMode | 四種執行模式:POSTING/MAIN/BACKGROUND/ASYNC |
static volatile EventBus defaultInstance;
public static EventBus getDefault() {
if (defaultInstance == null) {
synchronized (EventBus.class) {
if (defaultInstance == null) defaultInstance = new EventBus();
}
}
return defaultInstance;
}
public class EventBusBuilder {
boolean logSubscriberExceptions = true; // 記錄異常
boolean logNoSubscriberMessages = true; // 無訂閱者提示
boolean sendSubscriberExceptionEvent = true; // 發送異常事件
boolean sendNoSubscriberEvent = true; // 發送無訂閱事件
boolean throwSubscriberException = false; // 拋出異常
boolean eventInheritance = true; // 支持事件繼承(父類/接口)
boolean strictMethodVerification = false; // 嚴格校驗方法簽名
ExecutorService executorService = Executors.newCachedThreadPool(); // 線程池
List subscriberInfoIndexes; // APT 索引支持
public EventBus build() { return new EventBus(this); }
}
關鍵屬性:eventInheritance 決定是否向父類/接口傳遞;executorService 控制異步執行策略。
// 事件類型 -> 訂閱者列表(CopyOnWriteArrayList 保證線程安全遍歷)
private final Map, CopyOnWriteArrayList> subscriptionsByEventType;
// 訂閱者 -> 其訂閱的事件類型集合
private final Map
static class PostingThreadState {
final List
post(event) → 獲取線程狀態 → 入隊 → postSingleEvent()postSingleEvent() → 若 eventInheritance 則遍歷父類/接口 → postSingleEventForEventType()postSingleEventForEventType() → 獲取訂閱列表 → 遍歷調用 postToSubscription()postToSubscription() → 根據 ThreadMode 分發private void postSingleEvent(Object event, PostingThreadState postingState) {
Class> eventClass = event.getClass();
boolean subscriptionFound = false;
if (eventInheritance) {
List> eventTypes = new ArrayList<>();
for (Class> clazz = eventClass; clazz != null; clazz = clazz.getSuperclass()) {
eventTypes.add(clazz);
for (Class> iface : clazz.getInterfaces()) eventTypes.add(iface);
}
for (int h = 0, countTypes = eventTypes.size(); h < countTypes; h++) {
Class> clazz = eventTypes.get(h);
subscriptionFound |= postSingleEventForEventType(event, postingState, clazz);
}
} else {
subscriptionFound = postSingleEventForEventType(event, postingState, eventClass);
}
if (!subscriptionFound && sendNoSubscriberEvent) {
post(new NoSubscriberEvent(this, event));
}
}
private void postToSubscription(Subscription sub, Object event, boolean isMainThread) {
switch (sub.subscriberMethod.threadMode) {
case POSTING:
invokeSubscriber(sub, event); // 直接在發布線程執行
break;
case MAIN:
if (isMainThread) invokeSubscriber(sub, event);
else mainThreadPoster.enqueue(sub, event); // 切到主線程
break;
case BACKGROUND:
if (!isMainThread) invokeSubscriber(sub, event);
else backgroundPoster.enqueue(sub, event); // 切到後台線程池
break;
case ASYNC:
asyncPoster.enqueue(sub, event); // 直接丟線程池並發
break;
}
}
public class HandlerPoster extends Handler {
private final PendingPostQueue queue;
private boolean handlerActive;
void enqueue(Subscription sub, Object event) {
PendingPost pendingPost = PendingPost.obtainPendingPost(sub, event);
synchronized (this) {
queue.enqueue(pendingPost);
if (!handlerActive) {
handlerActive = true;
sendMessage(obtainMessage()); // 觸發 handleMessage
}
}
}
@Override
public void handleMessage(Message msg) {
long started = SystemClock.uptimeMillis();
while (true) {
PendingPost pendingPost = queue.poll();
if (pendingPost == null) {
synchronized (this) {
pendingPost = queue.poll();
if (pendingPost == null) { handlerActive = false; return; }
}
}
eventBus.invokeSubscriber(pendingPost);
// 限制單次處理時間,避免阻塞主線程過久
if (SystemClock.uptimeMillis() - started >= maxMillisInsideHandleMessage) {
sendMessage(obtainMessage()); // 重新調度
return;
}
}
}
}
關鍵點:關聯主線程 Looper,通過 maxMillisInsideHandleMessage(默認 10ms)分片執行,防止 ANR。
final class BackgroundPoster implements Runnable {
private final PendingPostQueue queue;
private volatile boolean executorRunning;
public void enqueue(Subscription sub, Object event) {
PendingPost pendingPost = PendingPost.obtainPendingPost(sub, event);
synchronized (this) {
queue.enqueue(pendingPost);
if (!executorRunning) {
executorRunning = true;
eventBus.getExecutorService().execute(this);
}
}
}
@Override public void run() {
try {
while (true) {
PendingPost pendingPost = queue.poll(1000); // 帶超時輪詢
if (pendingPost == null) {
synchronized (this) {
pendingPost = queue.poll();
if (pendingPost == null) { executorRunning = false; return; }
}
}
eventBus.invokeSubscriber(pendingPost);
}
} catch (InterruptedException e) { /* log */ }
finally { executorRunning = false; }
}
}
單線程順序處理,適合耗時但需串行的任務(如資料庫寫入)。
class AsyncPoster implements Runnable {
private final PendingPostQueue queue;
public void enqueue(Subscription sub, Object event) {
PendingPost pendingPost = PendingPost.obtainPendingPost(sub, event);
queue.enqueue(pendingPost);
eventBus.getExecutorService().execute(this); // 每個事件獨立提交任務
}
@Override public void run() {
PendingPost pendingPost = queue.poll();
if (pendingPost != null) eventBus.invokeSubscriber(pendingPost);
}
}
每次 enqueue 都提交新任務到線程池,實現真正並發,適合獨立無序的耗時操作(如網絡請求、圖片加載)。
class SubscriberMethod {
final Method method;
final ThreadMode threadMode;
final Class> eventType;
final int priority;
final boolean sticky;
// 構造時校驗:public、非靜態、單參數、@Subscribe 註解
}
@Subscribe 且符合簽名的方法SubscriberMethod 列表Subscription,存入兩級 MapEventBus 3.0 引入註解處理器,編譯期生成索引類,運行時直接讀取避免反射掃描,大幅提升啟動速度。EventBusBuilder.ignoreGeneratedIndex 可強制禁用。
throwSubscriberException 或訂閱 SubscriberExceptionEventEventBus 以「約定優於配置」的設計,在 Android 事件通信領域確立了統治地位。理解其源碼機制,有助於排查疑難雜癥(如事件丟失、ANR、內存洩漏),也能在造輪子時借鑒其優雅的線程調度架構。