您的位置:首页 > 其它

EventBus---消息的发送与处理(一)

2015-12-18 09:11 330 查看
<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">前面分析了EventBus的注册流程,下面就来分析下EventBus的消息发送和处理流程。在《EventBus---注册》中,EventBus将注册类中的系统方法按照处理消息的类型(系统函数的参数类型)进行了分类,并记录了一个注册类中所有参数类型,接下来就详细分析下。</span>


EventBus发送消息时暴露出来的方法有两个,上源码!

 

public void post(Object event)
public void postSticky(Object event)


第一个方法是发送一个普通的消息,第二个是发送一个粘性消息。其实第二个和第一个差不多,只是在发送粘性广播的时候,发送之前将发送的广播保存起来,以便有类在注册接收相同类型的广播时将粘性广播发送给接收者进行处理,和android上的粘性广播一个道理。我们就着重来分析第一种消息发送,上源码!

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;
}
}
}在发送消息时,首先活发送消息的线程的状态。currentPostingThreadState是ThreadLocal,主要用于记录当前正在处理的消息队列,消息处理的状态,是否在主线程,已经正在处理的消息和接收消息的系统函数。通过以上的源码,我们发现发送消息的处理步骤:(1)获取currentPostingThreadState;(2)将需要发送的消息添加到消息队列中;(3)判断系统是否正在发送消息;(4)设置isMainThread;(5)判断消息发送是否已经被取消;(6)发送消息;(7)循环取出消息队列中的消息进行处理;(8)将postingThread的标志重置。

1、postSingleEvent()

      前面已经大致了解了下消息的发送流程,但是还没有具体讨论消息的发送,下面就从postSingleEvent()开始深入分析消息的发送和处理流程。

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));
}
}
}在postSingleEvent()函数处理待发送的消息时,首先获得消息的类型,也即是eventClass,接着判断消息的发送是否支持eventInheritance。eventInheritance描述的是一种消息发送的策略,如果eventInheritance是真,则在发送消息时不仅将消息发送给处理此消息类型的系统函数,也会将消息发送给处理此消息类型的父类的系统函数,因此系统默认eventIbheritance默认是false,这样可以显著提高消息的发送效率达20%左右。上面的源码中,可以发现如果系统打开了eventInheritance,首先去找到消息类型的所有父类,然后将消息发送给所有能够给处理这些类型的系统函数,只要有一个处理成功就设置subscriptionFound为真,如果没有打开eventInheritance,则仅仅将消息发送给能够处理消息本身类型的系统函数。下面我们就分析下postSingleEventForEventType()。
2、postSingleEventForEventType()

       还是把源码贴出来我们来剖析!

        private boolean postSingleEventForEventType(Object event, PostingT
9d0b
hreadState 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;
    }
在注册的时候,我们已经将系统方法按照处理的消息类型进行分类保存在Map中,键为消息类型,值为处理此类型的消息列表。进入postSingleEventForEventType()后,首先获得处理eventClass类型消息的系统函数列表,然后就在循环中处理列表中每个系统函数的调用,同时将postState中当前正在处理的消息设置为当前的消息,当前正在处理消息的方法为当前正在调用的消息处理方法,而后,去调用postToSubscription()函数去处理这个消息。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: