EventBus的post过程
首先看post(Object event)函数实现
//EventBus.java
/** Posts the given event to the event bus. */
public void post(Object event) {
//取得当前线程的PostingThreadState对象
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;
}
}
}
从上面的代码注释中我们可以发现分发事件的核心代码在 postSingleEvent(Object event, PostingThreadState postingState) 中,下面看一下具体实现
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));
}
}
}
- 这里涉及一个概念:事件继承;那么什么是所谓的事件继承呢?通俗点讲就是事件B继承自事件A,在发送事件B的时候也会发送事件A,默认是事件继承的,如果不需要请自定义EventBus,不要使用默认的
- 注意这里的sendNoSubscriberEvent变量,如果不需要在没有订阅者的时候发送没有订阅者消息,也是需要自定义EventBus的
- 打印没有订阅者也是如此
下面我们分析一下 postSingleEventForEventType(Object event, PostingThreadState postingState, Class eventClass),看一下函数实现
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;
}
代码不复杂,可以看出来发送事件的代码是第14行的postToSubscription函数,下面看一下这个函数的实现
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);
}
}
上面的代码就是具体的事件分发过程了,可以看到事件会根据threadMode的类型决定使用哪种方式分发事件,如果忘了threadMode,请看以前的文章EventBus简单使用
1. 先说POSTING模式,在这个模式下,事件处理函数是和事件发送线程中执行的,所以就直接调用invokeSubscriber函数处理事件
2. 在MAIN模式下,如果发送事件函数是在主线程中,那么就直接调用invokeSubscriber函数处理事件,如果不是主线程,需要切换线程到主线程,切换线程用的是Handler
3. 在BACKGROUND模式下,如果线程是主线程,就需要切换线程到background线程中,如果不是主线程,就直接调用invokeSubscriber处理事件
4. 在ASYNC模式下,切换线程到其他非主线程中处理事件