EventBus使用及源码分析(二)

423 阅读3分钟

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方法。