上篇文章我们说了register的流程,这篇呢我们来捋顺一下post流程是怎么工作的,其实post流程相对来说更为简单。当然这篇文章我们不说线程切换的问题,关于线程切换的问题,我们放在下片文章来说。
我们先看一下EventBus的post方法
public void post(Object event) {
//从ThreadLocal中拿到所属线程的PostingThreadState
PostingThreadState postingState = currentPostingThreadState.get();
//拿到事件队列
List<Object> eventQueue = postingState.eventQueue;
//把事件添加到队列中
eventQueue.add(event);
//判断是否出去发送状态
if (!postingState.isPosting) {//如果不是发送状态,则进入循环
//是否为主线程
postingState.isMainThread = isMainThread();
//修改PostingThreadState为发送状态
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;
}
}
}
所有的代码注释的很清楚,ThreadLocal隔离保存了每个线程的PostingThreadState,我们查看PostingThreadState源码可以知道,这个类保存了事件发送时的一些特征属性。具体的发送,我们查看postSingleEvent方法:
private void postSingleEvent(Object event, PostingThreadState postingState) throws Error {
//获取事件的class
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) {
logger.log(Level.FINE, "No subscribers registered for event " + eventClass);
}
if (sendNoSubscriberEvent && eventClass != NoSubscriberEvent.class &&
eventClass != SubscriberExceptionEvent.class) {
post(new NoSubscriberEvent(this, event));
}
}
}
同样,相关的功能注释很清楚了。这里eventInheritance这个变量要注意一下,这个变量的含义:是否考虑事件的遗传问题。什么意思呢?我举一个例子:
比如A类实现了B接口,Test1Activity注册了EventBus,并且其中test方法被Subscribe注释,方法的参数为B类,Test2Activity中进行了post操作,事件类型为A。如果eventInheritance为true,那么test方法可以收到传递的事件
这个值是可以手动设置的,默认值是true。
具体的发送,需要再看postSingleEventForEventType方法:
private boolean postSingleEventForEventType(Object event, PostingThreadState postingState, Class<?> eventClass) {
CopyOnWriteArrayList<Subscription> subscriptions;
synchronized (this) {
//根据事件class,拿到Subscription集合
subscriptions = subscriptionsByEventType.get(eventClass);
}
if (subscriptions != null && !subscriptions.isEmpty()) {
for (Subscription subscription : subscriptions) {
//设置相关属性
postingState.event = event;
postingState.subscription = subscription;
boolean aborted;
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;
}
我们可以看到,通过eventClass拿到了Subscription集合,这个Subscription相信大家应该有印象,在register流程中提到过它,Subscription主要存储了注册类及方法的相关属性
之后就调用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 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的判断,我们暂时不去看线程切换的功能,我们下片文章具体探究。无论是哪个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,执行到了具体类的具体方法,这样就收到了相关的事件。
以上就是EventBus的post流程,有问题欢迎留言。