源码解析-post

来源:互联网 发布:琉璃神社新的域名 编辑:程序博客网 时间:2024/06/07 20:33

1、应用方调用如下:

EventMsg msg = new EventMsg();msg.setMsg("hello eventBus");EventBus.getDefault().post(msg);

2、post()

public void post(Object event) {    // PostingThreadState保存着事件队列和线程状态信息    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;        }    }}

在PostingThreadState中保存了事件队列,以及线程的一些状态信息。首先从PostingThreadState对象中取出事件队列,然后再将当前的事件插入到事件队列当中。最后将队列中的事件依次交由postSingleEvent方法进行处理,并移除该事件。下面就在进入postSingleEvent方法中看一下。

2.1 postSingleEvent

private void postSingleEvent(Object event, PostingThreadState postingState) throws Error {    Class<?> eventClass = event.getClass();    boolean subscriptionFound = false;    if (eventInheritance) {        // 获取所有事件并存放在List中,这里表示事件存在继承关系,向上查找事件的父类        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));        }    }}

对于eventInheritance表示是否向上查找事件的父类。它的默认值为true,可以通过在EventBusBuilder中来进行配置。当eventInheritance为true时,则通过lookupAllEventTypes找到所有的父类事件并存发在List中,然后通过postSingleEventForEventType方法对事件逐一处理。

2.2 postSingleEventForEventType

private boolean postSingleEventForEventType(Object event, PostingThreadState postingState, Class<?> eventClass) {    // 同步取出该事件对应的Subscription集合    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;}

还记得在订阅者进行注册时候,以订阅事件作为Key,将Subscription的List集合作为Value保存到了一个Map集合当中。而就在这个方法中通过事件类型取出Subscription的List集合,然后调用了postToSubscription方法来处理事件并执行订阅方法。下面再来看一下postToSubscription方法。

2.3 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 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);    }}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);    }}

这一路对订阅事件的分发,总算差不多要到头了。在这里取出订阅方法的线程模式,之后根据订阅方法所设置的线程模式来选择线程来执行订阅方法的线程。

订阅方法的线程模式为MAIN的时候。提交事件的线程是主线程则直接执行invokeSubscriber方法。否则加入到mainThreadPoster对象的队列中,而mainThreadPoster对象他是HandlerPoster对象。HandlerPoster继承自Handler,也即是通过Handler将订阅方法切换到主线程执行。