在《EventBus---消息的发送与处理(一)》中,已经说到发送消息,系统已经根据系统函数接收的消息的类型筛选除了处理消息的系统函数列表,下面就是使用循环将消息发送给系统函数列表中的系统函数。后面就进入到系统函数的消息处理阶段。还是上源码!
private void postToSubscription(Subscription subscription, Object event, boolean isMainThread) {
switch (subscription.subscriberMethod.threadMode) {
case PostThread:
invokeSubscriber(subscription, event);
break;
case MainThread:
if (isMainThread) {
invokeSubscriber(subscription, event);
} else {
mainThreadPoster.enqueue(subscription, event);
}
break;
case BackgroundThread:
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);
}
}
系统在发送给subscription消息event时,会首先判断函数处理消息的模式,在《EventBus--注册》中已经说过,每个系统函数处理消息有四种模式,分别为:在当前线程;在主线程;在后台线程;在异步线程。
(1)如果为当前线程,则直接将消息发送给系统函数进行处理。我们看下当前线程的消息处理,上源码!
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);
}
}
可以看见,如果在当前线程处理消息,则直接用反射对方法进行调用,将消息座位参数传递给方法即可。
(2)如果为主线程,则首先要判断当前线程是否为主线程,如果为主线程则和(1)中一样进行处理,否则传递给mainThreadPoster进行处理。
mainThreadPoster中有保存消息的消息队列,这个队列是一个链表,每次有消息便将消息插入到链表的末尾,插入成功后给handler发送消息,handler收到消息后就开始在主线程中循环处理消息,直至消息队列中没有消息为止。
(3)如果为后台进程,则首先判断当前线程是否为后台线程,如果为后台线程则和(1)中一样进行处理,否则传递给backgroudPoster进行处理。
如果当前线程不是后台线程,则会调用后台消息处理BackgroudPoster进行处理。在BackgroundPoster中也有一个和(2)中一样的队列,保存的是需要处理的后台消息。将消息插入队列后,会循环调用后台线程执行消息处理,直至消息队列中没有消息为止。
(3)如果为异步线程,则传递给asyncPoster进行处理。
如果是异步线程,则调用asyncPoster进行处理,asyncPoster中也有一个和(2)中一样的队列,保存的是需要处理的异步消息。将消息插入到队列后,会调用异步任务执行消息处理。