EventBus源码解析二

来源:互联网 发布:php mongodb连接池配置 编辑:程序博客网 时间:2024/06/11 20:05

EventBus的post过程

首先看post(Object event)函数实现

    //EventBus.java    /** Posts the given event to the event bus. */    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;            }        }    }

从上面的代码注释中我们可以发现分发事件的核心代码在 postSingleEvent(Object event, PostingThreadState postingState) 中,下面看一下具体实现

    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));            }        }    }
  1. 这里涉及一个概念:事件继承;那么什么是所谓的事件继承呢?通俗点讲就是事件B继承自事件A,在发送事件B的时候也会发送事件A,默认是事件继承的,如果不需要请自定义EventBus,不要使用默认的
  2. 注意这里的sendNoSubscriberEvent变量,如果不需要在没有订阅者的时候发送没有订阅者消息,也是需要自定义EventBus的
  3. 打印没有订阅者也是如此

下面我们分析一下 postSingleEventForEventType(Object event, PostingThreadState postingState, Class eventClass),看一下函数实现

    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;                }                if (aborted) {                    break;                }            }            return true;        }        return false;    }

代码不复杂,可以看出来发送事件的代码是第14行的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);        }    }

上面的代码就是具体的事件分发过程了,可以看到事件会根据threadMode的类型决定使用哪种方式分发事件,如果忘了threadMode,请看以前的文章EventBus简单使用
1. 先说POSTING模式,在这个模式下,事件处理函数是和事件发送线程中执行的,所以就直接调用invokeSubscriber函数处理事件
2. 在MAIN模式下,如果发送事件函数是在主线程中,那么就直接调用invokeSubscriber函数处理事件,如果不是主线程,需要切换线程到主线程,切换线程用的是Handler
3. 在BACKGROUND模式下,如果线程是主线程,就需要切换线程到background线程中,如果不是主线程,就直接调用invokeSubscriber处理事件
4. 在ASYNC模式下,切换线程到其他非主线程中处理事件

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 孩子吐还拉稀怎么办 宝贝拉肚子又吐怎么办 小孩子发烧呕吐拉肚子怎么办 小孩受凉呕吐拉肚子怎么办 一周岁宝宝发烧怎么办 宝宝吃了吐怎么办 儿子喝水都吐怎么办 宝宝吐奶拉肚子怎么办 怀孕吐的厉害怎么办 孩子一直呕吐怎么办啊 仓鼠宝宝拉稀了怎么办 2岁有点拉稀怎么办 婴儿吃米粉腹泻怎么办 小儿胃寒呕吐怎么办 孩子突然一直吐怎么办 宝宝呕吐并发烧怎么办 宝宝发烧呕吐拉稀怎么办 小孩发高烧还吐怎么办 二个多月的宝宝拉肚子怎么办 宝宝肚子着凉吐怎么办 孩子胃着凉呕吐怎么办 一岁受凉呕吐怎么办 孩子着凉了呕吐怎么办 小孩受凉呕吐腹泻怎么办 宝宝胃受寒呕吐怎么办 一岁半宝宝受寒呕吐怎么办 治小儿反复发烧怎么办 海洋宝宝吃下去怎么办 两岁儿童拉肚子怎么办 14天宝宝拉肚子怎么办 小孩不消化引起发烧怎么办 宝宝胃胀呕吐怎么办 小儿胃胀不消化怎么办 4岁小儿腹胀怎么办 两岁半的宝宝吐怎么办 月子宝宝闹人怎么办 宝宝一周岁拉肚子怎么办 一岁幼儿呕吐怎么办 孩子受凉呕吐拉肚子怎么办 5岁儿童呕吐怎么办 小孩发烧老是吐怎么办