2.post()
EventBus的register解析: EventBus使用及源码分析(一)
/** Posts the given event to the event bus. */
public void post(Object event) {
//currentPostingThreadState是EventBus中的一个ThreadLocal对象,
//作用是为每个Thread都维护着一个State,其中存放各种信息。在这里获取当前线程的State。
PostingThreadState postingState = currentPostingThreadState.get();
List<Object> eventQueue = postingState.eventQueue;
eventQueue.add(event);
if (!postingState.isPosting) {
postingState.isMainThread = isMainThread();
postingState.isPosting = true;
if (postingState.canceled) {
throw new EventBusException("Internal error. Abort state was not reset");
}
try {
while (!eventQueue.isEmpty()) {
//调用postSingleEvent()方法
postSingleEvent(eventQueue.remove(0), postingState);
}
} finally {
postingState.isPosting = false;
postingState.isMainThread = false;
}
}
}
可以看到,这里的post是将event添加到队列中,然后再循环的从队列中获取event,再调用postSingleEvent()执行。
在这里会使用一个flag判断是否正在posting,使用了ThreadLocal后,每个线程都会有一个队列,是线程安全的。但是,如果subscriber的方法中再次调用post()方法,当前线程就会转而去执行新的post()方法,显然这里是要将post()的方法按照顺序依次执行。
private void postSingleEvent(Object event, PostingThreadState postingState) throws Error {
Class<?> eventClass = event.getClass();
boolean subscriptionFound = false;
if (eventInheritance) {
//lookupAllEventTypes方法是获取EventType的所有父类和接口
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) {
logger.log(Level.FINE, "No subscribers registered for event " + eventClass);
}
if (sendNoSubscriberEvent && eventClass != NoSubscriberEvent.class &&
eventClass != SubscriberExceptionEvent.class) {
//如果EventType并没有subscriber,则会post一个NoSubscriberEvent的事件。
post(new NoSubscriberEvent(this, event));
}
}
}
首先说明一下,如果不是使用EventBusBuilder手动创建EventBus,这里的eventInheritance/ sendNoSubscriberEvent默认是true。如果有一个EventType是一个名字为A的类继承了B父类,实现了C接口,eventInheritance为true时,EventType是A/B/C的订阅都会执行。
然后我们看看postSingleEventForEventType方法。
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;
}
//当调用cancelEventDelivery方法后postingState.canceled会变为true,所以aborted就会为true,
//在这里break掉,后面的Event就不会执行。
if (aborted) {
break;
}
}
return true;
}
return false;
}
我们回忆一下,subscriptionsByEventType这个map的key是eventType,value是subscription列表(一个subscription包含了订阅者,以及一个订阅方法这些信息)。所以这里从subscriptionsByEventType中取出这个eventType的所有subscription,然后调用postToSubscription()方法。
private void postToSubscription(Subscription subscription, Object event, boolean isMainThread) {
switch (subscription.subscriberMethod.threadMode) {
case POSTING:
invokeSubscriber(subscription, event);
break;
case MAIN:
//会通过Handler执行
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:
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判断怎么执行,其实最后都会调用到invokeSubscriber()方法,所以我们直接看下这个方法。
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);
}
}
可以看到,最后通过invoke()调用方法,至此post()方法的代码解析完毕。
总结一下,通过post()方法传入了EventType,然后有一个map维护了这个EventType的所有subscription信息(包括了subscribe方法和subscriber对象),获取subscription后,通过invoke调用这个subscribe方法。