title: EventBus 源碼分析
date: 2017-09-15 09:38:14
tags: [Source Code]
categories: android
可見的設計模式:
- 單例模式
- 構建者模式
- 中介模式(EventBus 自己就是中介者)
- 對象池模式 (pendingPostPool 延遲事件池)
數據結構知識:
- 鏈表結構(PendingPostQueue 事件隊列)
EventBus.class
創建方法 是單例模式
static volatile EventBus defaultInstance;
/** 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;
}
創建方法使用了 構建者模式:
// 自定義 構建者
public static EventBusBuilder builder() {
return new EventBusBuilder();
}
// 默認的構造方法,里面使用了默認的構建者
private static final EventBusBuilder DEFAULT_BUILDER = new EventBusBuilder();
public EventBus() {
this(DEFAULT_BUILDER);
}
EventBus(EventBusBuilder builder) {
subscriptionsByEventType = new HashMap<>();
typesBySubscriber = new HashMap<>();
stickyEvents = new ConcurrentHashMap<>();
mainThreadPoster = new HandlerPoster(this, Looper.getMainLooper(), 10);
backgroundPoster = new BackgroundPoster(this);
asyncPoster = new AsyncPoster(this);
indexCount = builder.subscriberInfoIndexes != nulbuilder.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;
}
幾個重要方法
注冊接收者 register
/**
* Registers the given subscriber to receive events. Subscribers must call {@l#unregister(Object)} once they
* are no longer interested in receiving events.
* <p/>
* Subscribers have event handling methods that must be annotated by {@link Subscribe}.
* The {@link Subscribe} annotation also allows configuration like {@link
* ThreadMode} and priority.
*/
public void register(Object subscriber) {
Class<?> subscriberClass = subscriber.getClass();
List<SubscriberMethod> subscriberMethodsubscriberMethodFinder.findSubscriberMethods(subscriberClass);
synchronized (this) {
for (SubscriberMethod subscriberMethod : subscriberMethods) {
subscribe(subscriber, subscriberMethod);
}
}
}
注冊一個事件的接收者。
-
List<SubscriberMethod> subscriberMethodsubscriberMethodFinder.findSubscriberMethods(subscriberClass);
這個方法獲取事件接收者類中定義的事件接收方法(使用 @Subscribe 注解的方法) - SubscriberMethod:對接收者接收方法的封裝
// Must be called in synchronized block
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("Subscriber " + subscriber.getClass() + " 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) {
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>).
Set<Map.Entry<Class<?>, Object>> entries = stickyEvents.entrySet();
for (Map.Entry<Class<?>, Object> entry : entries) {
Class<?> candidateEventType = entry.getKey();
if (eventType.isAssignableFrom(candidateEventType)) {
Object stickyEvent = entry.getValue();
checkPostStickyEventToSubscription(newSubscription, stickyEvent);
}
}
} else {
Object stickyEvent = stickyEvents.get(eventType);
checkPostStickyEventToSubscription(newSubscription, stickyEvent);
}
}
}
- Subscription: 封裝了事件接收者(Object)和 事件接收者內部事件接收方法(SubscriberMethod)
- EventBus 成員變量:
Map<Class<?>, CopyOnWriteArrayList<Subscription>> subscriptionsByEventType
存儲了 事件 和 事件接收者相關的Subscription - subscriptionsByEventType: 中會按照事件接收的優先級對 Subscription 進行排序
- eventType:實際上就是 事件.class
- EventBus 成員變量:
Map<Object, List<Class<?>>> typesBySubscriber
: 保存 key-接收者對象, value:eventType(事件.class) - sticky 事件的實現 ????
unregister 取消注冊
/** Unregisters the given subscriber from all event classes. */
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 {
Log.w(TAG, "Subscriber to unregister was not registered before: " + subscriber.getClass());
}
}
/** Only updates subscriptionsByEventType, not typesBySubscriber! Caller must update typesBySubscriber. */
private void unsubscribeByEventType(Object subscriber, Class<?> eventType) {
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) {
subscription.active = false;
subscriptions.remove(i);
i--;
size--;
}
}
}
}
- 從
typesBySubscriber
獲取 接收者對應的 【eventType s】 - 通過 【eventType s】 從
subscriptionsByEventType
刪除 eventType-List<Subscription> - 從
typesBySubscriber
刪除 接收者-【eventType s】
發送事件
/** Posts the given event to the event bus. */
public void post(Object event) {
PostingThreadState postingState = currentPostingThreadState.get();
List<Object> eventQueue = postingState.eventQueue;
eventQueue.add(event);
if (!postingState.isPosting) {
postingState.isMainThread = Looper.getMainLooper() == Looper.myLooper();
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;
}
}
}
- EventBus 成員變量:
ThreadLocal<PostingThreadState> currentPostingThreadState
- 這個方法中初始化了用于記錄發送事件的線程的線程狀態類:PostingThreadState
事件發送方法:
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);
}
if (!subscriptionFound) {
if (logNoSubscriberMessages) {
Log.d(TAG, "No subscribers registered for event " + eventClass);
}
if (sendNoSubscriberEvent && eventClass != NoSubscriberEvent.class &&
eventClass != SubscriberExceptionEvent.class) {
post(new NoSubscriberEvent(this, event));
}
}
}
-
lookupAllEventTypes(Class<?> eventClass)
方法通過 事件類 尋找 eventTypes(事件類集合) - EventBus 成員變量
Map<Class<?>, List<Class<?>>> eventTypesCache
實現 事件類-eventTypes 關聯
事件不同線程之前切換代碼:
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 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);
}
}
事件隊列
EventBus 成員變量:
private final HandlerPoster mainThreadPoster;
private final BackgroundPoster backgroundPoster;
private final AsyncPoster asyncPoster;
- mainThreadPoster:存放所有需要在主線程中執行的事件。
- backgroundPoster:存放所有需要在子線程中執行的事件。(使用 ExecutorService 獲取一個子線程讓后執行,BackgroundPoster 實現了 Runnable 接口)
- asyncPoster:存放所有需要在子線程中執行的事件(使用 ExecutorService 獲取一個子線程讓后執行,AsyncPoster 實現了 Runnable 接口)
BackgroundPoster vs AsyncPoster
區別
- 從事件隊列中取事件的時候:BackgroundPoster 采用延遲取事件(1000),AsyncPoster 馬上取事件
HandlerPoster.class
構造方法
是 Handler 的子類,在 EventBus 中創建,創建時使用 mainLopper 創建:
mainThreadPoster = new HandlerPoster(this, Looper.getMainLooper(), 10);
//...
HandlerPoster(EventBus eventBus, Looper looper, int maxMillisInsideHandleMessage)
成員變量
private final PendingPostQueue queue;
private final int maxMillisInsideHandleMessage;
private final EventBus eventBus;
private boolean handlerActive;
- queue: 需要在主線程執行的事件隊列
- eventBus:EventBus 對象
- handlerActive:記錄是否有事件正在執行
- maxMillisInsideHandleMessage:超時記錄
向隊列中添加一個事件
void enqueue(Subscription subscription, Object event) {
PendingPost pendingPost = PendingPost.obtainPendingPost(subscription, event);
synchronized (this) {
queue.enqueue(pendingPost);
if (!handlerActive) {
handlerActive = true;
if (!sendMessage(obtainMessage())) {
throw new EventBusException("Could not send handler message");
}
}
}
}
- 通過 Subscription(事件接收者Object 和 事件接收者內部事件處理方法SubscriberMethod 的封裝) 創建一個 PendingPost (延遲事件)
- handlerActive:如果為 true 表示事件隊列的處理機制已經啟動(這個機制會在 事件隊列queue 中的所有事件被處理完成后停止),如果為 false 表示當前事件處理機制處于停止狀態。
-
queue.enqueue(pendingPost);
: 向隊列中加入一個 延遲事件 -
sendMessage(obtainMessage())
: 啟動事件處理機制
handleMessage
@Override
public void handleMessage(Message msg) {
boolean rescheduled = false;
try {
long started = SystemClock.uptimeMillis();
while (true) {
PendingPost pendingPost = queue.poll();
if (pendingPost == null) {
synchronized (this) {
// Check again, this time in synchronized
pendingPost = queue.poll();
if (pendingPost == null) {
handlerActive = false;
return;
}
}
}
eventBus.invokeSubscriber(pendingPost);
long timeInMethod = SystemClock.uptimeMillis() - started;
if (timeInMethod >= maxMillisInsideHandleMessage) {
if (!sendMessage(obtainMessage())) {
throw new EventBusException("Could not send handler message");
}
rescheduled = true;
return;
}
}
} finally {
handlerActive = rescheduled;
}
}
- maxMillisInsideHandleMessage:內部定義為 10
- rescheduled:表示本次循環處理了一個事件
BackgroundPoster.class
實線了 Runnable 接口
成員變量
private final PendingPostQueue queue;
private final EventBus eventBus;
private volatile boolean executorRunning;
- queue: 事件隊列
- EventBus
- executorRunning: 事件處理機制(一個死循環)是否正在執行
添加事件
public void enqueue(Subscription subscription, Object event) {
PendingPost pendingPost = PendingPost.obtainPendingPost(subscription, event);
synchronized (this) {
queue.enqueue(pendingPost);
if (!executorRunning) {
executorRunning = true;
eventBus.getExecutorService().execute(this);
}
}
}
同樣的需要將 Subscription + event = PendingPost (將事件相關信息進行封裝,讓后放入事件隊列中處理)
添加事件后啟動事件處理機制
事件處理機制(死循環)
@Override
public void run() {
try {
try {
while (true) {
PendingPost pendingPost = queue.poll(1000);
if (pendingPost == null) {
synchronized (this) {
// Check again, this time in synchronized
pendingPost = queue.poll();
if (pendingPost == null) {
executorRunning = false;
return;
}
}
}
eventBus.invokeSubscriber(pendingPost);
}
} catch (InterruptedException e) {
Log.w("Event", Thread.currentThread().getName() + " was interruppted", e);
}
} finally {
executorRunning = false;
}
}
-
PendingPost pendingPost = queue.poll(1000);
: 延遲 1s 從隊列中取事件
AsyncPoster.class
class AsyncPoster implements Runnable {
private final PendingPostQueue queue;
private final EventBus eventBus;
AsyncPoster(EventBus eventBus) {
this.eventBus = eventBus;
queue = new PendingPostQueue();
}
public void enqueue(Subscription subscription, Object event) {
PendingPost pendingPost = PendingPost.obtainPendingPost(subscription, event);
queue.enqueue(pendingPost);
eventBus.getExecutorService().execute(this);
}
@Override
public void run() {
PendingPost pendingPost = queue.poll();
if(pendingPost == null) {
throw new IllegalStateException("No pending post available");
}
eventBus.invokeSubscriber(pendingPost);
}
}
和 BackgroundPoster 類似
接收者處理事件的方法
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);
}
}
-
method.invoke
調用接收者的事件接收方法(類似反射)
延遲事件處理:
void invokeSubscriber(PendingPost pendingPost) {
Object event = pendingPost.event;
Subscription subscription = pendingPost.subscription;
PendingPost.releasePendingPost(pendingPost);
if (subscription.active) {
invokeSubscriber(subscription, event);
}
}
重要的成員變量
private static final EventBusBuilder DEFAULT_BUILDER = new EventBusBuilder();
private static final Map<Class<?>, List<Class<?>>> eventTypesCache = new HashMap<>();
private final Map<Class<?>, CopyOnWriteArrayList<Subscription>> subscriptionsByEventType;
private final Map<Object, List<Class<?>>> typesBySubscriber;
private final Map<Class<?>, Object> stickyEvents;
private final ThreadLocal<PostingThreadState> currentPostingThreadState = new ThreadLocal<PostingThreadState>() {
@Override
protected PostingThreadState initialValue() {
return new PostingThreadState();
}
};
private final HandlerPoster mainThreadPoster;
private final BackgroundPoster backgroundPoster;
private final AsyncPoster asyncPoster;
private final SubscriberMethodFinder subscriberMethodFinder;
private final ExecutorService executorService;
- eventType: 實際上是 被發送的事件類 (CustomEvent.class)
- DEFAULT_BUILDER: 默認的構建者對象
- eventTypesCache:緩存 EventType(事件類.class) 和 EventType子類,EventType相關接口類
- subscriptionsByEventType:記錄 EventType(事件類) 和 事件接收者 之間的聯系
- typesBySubscriber: 記錄 事件接收對象(Object)和 EventType(事件類.class)
- stickyEvents: 記錄粘性事件
- currentPostingThreadState:記錄線程狀態
- mainThreadPoster:主線程事件隊列管理類(保存事件隊列,有從事件隊列中取事件給 EventBus 處理的功能)
- backgroundPoster:Background 事件類型的事件隊列管理類
- AsyncPoster:Async 事件類型的事件隊列管理類
- subscriberMethodFinder: 從 事件接收者 中解析 事件接收方法(加了 @Subscribe 注解的方法),獲取 SubscriberMethod
- executorService: 相當于線程池的作用,執行所有在子線程中執行的事件
EventBusBuilder.class
用于創建 EventBus
里面保存的參數有:
SubscriberMethod.class
對接收者接收方法的封裝
成員熟悉:
final Method method;
final ThreadMode threadMode;
final Class<?> eventType;
final int priority;
final boolean sticky;
/** Used for efficient comparison */
String methodString;
- method: 接收者中的事件接收方法,在執行事件處理的時候調用
- threadMode:記錄接受者事件接收方法在哪個線程中執行
- priority:優先級
- sticky:是否是粘性事件接收方法
- methodString:用來對比兩個接收方法是否是同一個
Subscription.class
封裝了事件接收者(Object)和 事件接收者內部事件接收方法(SubscriberMethod)
成員變量
final Object subscriber;
final SubscriberMethod subscriberMethod;
- subscriber: 事件接收者
- subscriberMethod:事件接收者中的事件接收方法
PostingThreadState.class
作用:
- 里面有事件隊列:EventBus 發送的數據存儲在隊列中
eventQueue
- 記錄線程狀態
/** For ThreadLocal, much faster to set (and get multiple values). */
final static class PostingThreadState {
final List<Object> eventQueue = new ArrayList<Object>();
boolean isPosting;
boolean isMainThread;
Subscription subscription;
Object event;
boolean canceled;
}
- isMainThread:記錄當前線程是不是主線程(在 EventBus post 方法中初始化)
- isPosting: 是否正在發送事件
private final ThreadLocal<PostingThreadState> currentPostingThreadState = new ThreadLocal<PostingThreadState>() {
@Override
protected PostingThreadState initialValue() {
return new PostingThreadState();
}
};
使用 ThreadLocal 實現線程內部的單例(保證一個線程中只有一個 PostingThreadState)
ExecutorService.class
表述了異步執行的機制,并且可以讓任務在后臺執行。 類似一個線程池。
PendingPost.class
一個延遲事件,不被馬上處理的事件都會被封裝成 PendingPost 對象,讓后被放置到指定的 事件隊列 中等待處理。
Subscription -》PendingPost
static PendingPost obtainPendingPost(Subscription subscription, Object event) {
synchronized (pendingPostPool) {
int size = pendingPostPool.size();
if (size > 0) {
PendingPost pendingPost = pendingPostPool.remove(size - 1);
pendingPost.event = event;
pendingPost.subscription = subscription;
pendingPost.next = null;
return pendingPost;
}
}
return new PendingPost(event, subscription);
}
延遲事件被處理的時候需要先從 PendingPost 中獲取 Subscription:
Subscription subscription = pendingPost.subscription;
然后釋放延遲事件:
static void releasePendingPost(PendingPost pendingPost) {
pendingPost.event = null;
pendingPost.subscription = null;
pendingPost.next = null;
synchronized (pendingPostPool) {
// Don't let the pool grow indefinitely
if (pendingPostPool.size() < 10000) {
pendingPostPool.add(pendingPost);
}
}
}
構造方法
private PendingPost(Object event, Subscription subscription) {
this.event = event;
this.subscription = subscription;
}
是私有的,只能通過靜態方法創建 PendingPost
成員變量
private final static List<PendingPost> pendingPostPool = new ArrayList<PendingPost>();
Object event;
Subscription subscription;
PendingPost next;
- pendingPostPool: 延遲事件池,較少不斷創建對象對性能的消耗。
- event:是用戶發送的 事件對象
PendingPostQueue.class 事件隊列的實現
final class PendingPostQueue {
private PendingPost head;
private PendingPost tail;
synchronized void enqueue(PendingPost pendingPost) {
if (pendingPost == null) {
throw new NullPointerException("null cannot be enqueued");
}
if (tail != null) {
tail.next = pendingPost;
tail = pendingPost;
} else if (head == null) {
head = tail = pendingPost;
} else {
throw new IllegalStateException("Head present, but no tail");
}
notifyAll();
}
synchronized PendingPost poll() {
PendingPost pendingPost = head;
if (head != null) {
head = head.next;
if (head == null) {
tail = null;
}
}
return pendingPost;
}
synchronized PendingPost poll(int maxMillisToWait) throws InterruptedException {
if (head == null) {
wait(maxMillisToWait);
}
return poll();
}
}
單鏈結構
- 當隊列中只有一個事件的時候,head,tail 指向同一個事件對象
head = tail = pendingPost;
,它們的 next 都指向 null - 當隊列中事件 = 2 的時候,head.next 指向第二個事件,tail.next 指向 自己
- 當隊列中事件 >2 的時候,最后一個事件(tail.next 指向 自己), 中間的事件(mid.next 指向下一個事件)
SubscriberMethodFinder
作用:從事件接收者中獲取所有的事件接收方法 得到 List<SubscriberMethod>