EventBus 源码分析(下篇)

作者: 糖葫芦_倩倩 | 来源:发表于2018-09-30 14:14 被阅读9次

    上篇 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<Object> 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<Object> eventQueue = new ArrayList<Object>();
            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<Subscription> 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 源码分析(下篇)

        本文链接:https://www.haomeiwen.com/subject/nytwoftx.html