EventBus 源码分析(下篇)

微信扫一扫,分享到朋友圈

EventBus 源码分析(下篇)

上篇 EventBus 源码分析(上篇)
说到注册订阅的前半部分,此篇用来分析发送事件到接收事件这个过程。

1. 发送事件

示例:

EventBus.getDefault().post(new RemindBean("2018-02-12","happy"));

post
:

/** Posts the given event to the event bus. */
    public void post(Object event) {
      - 1.获取当前线程的postingThreadState 对象
        PostingThreadState postingState = currentPostingThreadState.get();
      - 2. 获取里面那个事件队列
        List eventQueue = postingState.eventQueue;
        - 3. 将事件添加到队列中去
        eventQueue.add(event);

      - 4. 判断当前的event 是否在 posting
        if (!postingState.isPosting) {
            - 5. 是否是主线程
            postingState.isMainThread = Looper.getMainLooper() == Looper.myLooper();
            postingState.isPosting = true;
            - 6. 判断是否取消
            if (postingState.canceled) {
                throw new EventBusException("Internal error. Abort state was not reset");
            }
            try {
                while (!eventQueue.isEmpty()) {//不为空,进入循环
                    - 7.按照顺序,post一个 remove一个
                    postSingleEvent(eventQueue.remove(0), postingState);
                }
            } finally {
                postingState.isPosting = false;
                postingState.isMainThread = false;
            }
        }
    }

PostingThreadState
大概看一眼

final static class PostingThreadState {
        final List eventQueue = new ArrayList();
        boolean isPosting;
        boolean isMainThread;
        Subscription subscription;
        Object event;
        boolean canceled;
    }

再就是 postSingleEvent(eventQueue.remove(0), postingState);
方法:

private void postSingleEvent(Object event, PostingThreadState postingState) throws Error {
         - 1. 获取event的字节码(例如就是:RemindBean.class)
        Class eventClass = event.getClass();
        boolean subscriptionFound = false;
      
        if (eventInheritance) {//默认为true
          - 2. 根据eventClass 的字节码查找
            List<Class> eventTypes = lookupAllEventTypes(eventClass);
            int countTypes = eventTypes.size();
            - 3.循环遍历
            for (int h = 0; h < countTypes; h++) {
                Class clazz = eventTypes.get(h);
                - 4.根据事件,字节码查找订阅者
                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));
            }
        }
    }

postSingleEventForEventType
:

private boolean postSingleEventForEventType(Object event, PostingThreadState postingState, Class eventClass) {
        CopyOnWriteArrayList subscriptions;
        synchronized (this) {
          - 1.根据字节码取出subscriptions,还记得我们之前在subscribe这个方法的时候,
把subscrber,subscriberMethod 封装成一个subscription 对象。

            subscriptions = subscriptionsByEventType.get(eventClass);
        }
        if (subscriptions != null && !subscriptions.isEmpty()) {
            for (Subscription subscription : subscriptions) {
                - 2. 取出每一个subscription 对象
                postingState.event = event;
                postingState.subscription = subscription;
                boolean aborted = false;
                try {
                  - 3. post到相应的线程中回调
                    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;
    }

postToSubscription
: 根据定义的不同线程,调用相应的方法

private void postToSubscription(Subscription subscription, Object event, boolean isMainThread) {
        switch (subscription.subscriberMethod.threadMode) {
            case POSTING://一般没定义的,这个就是post在哪个线程,响应就在哪个线程执行
                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);
        }
    }

invokeSubscriber
:

void invokeSubscriber(Subscription subscription, Object event) {
        try {
          - 反射拿到字节码clazz 反射调用方法,就收到消息了
            subscription.subscriberMethod.method.invoke(subscription.subscriber, event);
        } catch (InvocationTargetException e) {
            handleSubscriberException(subscription, event, e.getCause());
        } catch (IllegalAccessException e) {
            throw new IllegalStateException("Unexpected exception", e);
        }
    }

end.

浙江首个省县合作融媒体中心在青田启用 打通媒体融合“最后一公里”

上一篇

从垂直到多元,聚美的昨日辉煌与今夕衰落

下一篇

你也可能喜欢

EventBus 源码分析(下篇)

长按储存图像,分享给朋友