«

Android之EventBus概述及源码解析(雷惊风)

时间:2024-3-2 19:47     作者:韩俊     分类: Android


前段时间公司在项目中用到了Android三方开源库—EventBus。一直没时间总结,只能抽周末点时间总结一下,其中也借鉴了一些前辈的智慧。好了废话不多少,开始吧... ...

一、简单介绍。

在Android中当我们做完一件事在去通知其他模块进行后续任务的时候(下载完成,更新界面;评论成功,更新其他页面评论显示或条数增加等等),也有很多方法,比如Handler、BroadCastReceiver、Interface回调等,其实也是很好用的,但是他们在一定程度上是存在耦合度的,同时,用起来有时候也有点小复杂,EventBus的出现使我们完成同样的功能节省了不少时间,它代码简单,使用方便,充分降低了任务已经完成者与任务后续进行者之间的耦合度,所有的事件都交由EventBus这个类来管理。

二、涉及到的模块。

想通过Eventbus完成事件传递,至少要涉及3个部分,订阅者、发布者、事件,下边逐个简单介绍。

1.订阅者
订阅者就是我们任务完成后,需要更新页面的那些类,我们的每一个订阅者都可以订阅一个或多个事件对象,当发布者发布对应事件后,EventBus会查找所有订阅了本事件的所有订阅者,并执行订阅者操作类中相应的OnEvent*(Object)方法,完成对应操作。

订阅方法:EventBus.getDefault().register(this);这里EventBus用到了单例模式,在单例模式中用到了双重判读的方式保证并发访问,后续会为大家介绍。
2.发布者

发布者就是我们在完成任务后要通知订阅者更新最新信息的那个模块。简单来说,就是就是发布某个事件的对象,当发布者完成特定任务后,发布事件,事件总线EventBus通过事件获取对应的订阅者列表,循环执行订阅者中对应的OnEvent*(Object)事件响应函数。

发布事件方法:EventBus.getDefault().post(EventOb);

3.事件
就是一个我们自己定义的对象。可以携带一些处理后的信息。分为普通事件和 Sticky事件,相对于一般事件,Sticky事件不同之处在于,当事件发布后,再有订阅者开始订阅该类型事件,依然能收到该类型事件最近一个
Sticky事件。

三、用到的方法及作用。

1.EventBus.getDefault().register(this);

注册当前类到事件总线EventBus。This参数为当前activity的上下文对象。写在订阅者对象中。

2.EventBus.getDefault().post(new EventOB());

发布一个EventOB事件到事件总线EventBus中,EventOB为发布的事件类型,也就是一个对象。

3.Public void onEvent/onEvenMainThread /BackgroundThread/Async(){};

当发布者发布事件后,EventBus找到订阅者后通过订阅者的 ThreadMode名称类型在相应线程执行内部代码。ThreadMode共四种:

①PostThread:直接调用订阅者的事件响应函数;

②MainThread 如果发布线程就是主线程,则直接调用订阅者的事件响应函数,否则通过主线程的 Handler发送消息在主线程中处理,调用订阅者的事件响应函数;

③BackgroundThread 如果发布线程是主线程,则启动异步线程去处理,否则直接直接调用订阅者的事件响应函数;

④Async ,启动异步线程去处理,调用订阅者的事件响应函数。

4.EventBus.getDefault().unRegister(this);

取消当前类订阅。



四、源码分析。

好了,通过前边的大致介绍,相信大家对EventBus已经有了一个大致的了解,从现在开始进入对EventBus更深入的了解吧,让我们看看它的内部实现原理。

1.订阅流程。EventBus.getDefault().register(this);

 EventBus.getDefault()
 public static EventBus getDefault() {
        if (defaultInstance == null) {
            synchronized (EventBus.class) {
                if (defaultInstance == null) {
                    defaultInstance = new EventBus();
                }
            }
        }
        return defaultInstance;
    }
对于defaultInstance的双重判断,防止线程并发访问产生多个对象。

首先看一下它的功能流程图:
废话不多少,上源码:
<span style="font-size:18px;">public void register(Object subscriber) {
        register(subscriber, false, 0);
    } 
public void register(Object subscriber, int priority) {
        register(subscriber, false, priority);
    }
public void registerSticky(Object subscriber) {
        register(subscriber, true, 0);
    } 
public void registerSticky(Object subscriber, int priority) {
        register(subscriber, true, priority);
    }
private synchronized void register(Object subscriber, boolean sticky, int priority) {
        List<SubscriberMethod> subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriber.getClass());
        for (SubscriberMethod subscriberMethod : subscriberMethods) {
            subscribe(subscriber, subscriberMethod, sticky, priority);
        }
    }</span>


我们可以看上边代码,不管你采用哪中注册方式,其实它最终都调用了三个参数的构造方法,好吧,我们对他进行一下解剖,呵呵: 首先,我们看一下三个参数,subscriber:我们注册时传递过来的acticity上下文对象;sticky:是否粘性;priority:优先级设置,EventBus会根据我们设置的优先级进行排序。 register方法中分为两部分: 1.通过subscriberMethodFinder得到了subscriberMethods;(subscriberMethodFinder订阅者响应函数信息存储和查找类。) 2.for循环遍历subscriberMethods。好,接着往下走,看一下
subscriberMethodFinder.findSubscriberMethods(subscriber.getClass());
List<SubscriberMethod> findSubscriberMethods(Class<?> subscriberClass) {
        String key = subscriberClass.getName();
        List<SubscriberMethod> subscriberMethods;
    //从缓存中获取当前对象中所有的OnEvent*()方法;
        synchronized (methodCache) {
            subscriberMethods = methodCache.get(key);
        }
        if (subscriberMethods != null) {
            return subscriberMethods;
        }
        subscriberMethods = new ArrayList<SubscriberMethod>();
        Class<?> clazz = subscriberClass;
        HashSet<String> eventTypesFound = new HashSet<String>();
        StringBuilder methodKeyBuilder = new StringBuilder();
    //循环当前类及父类;
        while (clazz != null) {
        //过滤所有的系统类;
            String name = clazz.getName();
            if (name.startsWith("java.") || name.startsWith("javax.") || name.startsWith("android.")) {
                // Skip system classes, this just degrades performance
                break;
            }

            // Starting with EventBus 2.2 we enforced methods to be public (might change with annotations again)
    //得到所有的公有方法;
            Method[] methods = clazz.getDeclaredMethods();
            for (Method method : methods) {
                String methodName = method.getName();
        //判断是不是以“onEvent”开头的方法;ON_EVENT_METHOD_NAME = "onEvent";
                if (methodName.startsWith(ON_EVENT_METHOD_NAME)) {
        //得到修饰符;
                    int modifiers = method.getModifiers();
        //是public并且不是ABSTRACT或static的;
                    if ((modifiers & Modifier.PUBLIC) != 0 && (modifiers & MODIFIERS_IGNORE) == 0) {
            //得到参数列表;
                        Class<?>[] parameterTypes = method.getParameterTypes();
                        if (parameterTypes.length == 1) {
                            String modifierString = methodName.substring(ON_EVENT_METHOD_NAME.length());
                            ThreadMode threadMode;
               //根据modifierString对ThreadMode进行赋值;
                            if (modifierString.length() == 0) {
                                threadMode = ThreadMode.PostThread;
                            } else if (modifierString.equals("MainThread")) {
                                threadMode = ThreadMode.MainThread;
                            } else if (modifierString.equals("BackgroundThread")) {
                                threadMode = ThreadMode.BackgroundThread;
                            } else if (modifierString.equals("Async")) {
                                threadMode = ThreadMode.Async;
                            } else {
                //判断当前类是不是被我们在初始时已经过滤掉了;
                                if (skipMethodVerificationForClasses.containsKey(clazz)) {
                                    continue;
                                } else {
                                    throw new EventBusException("Illegal onEvent method, check for typos: " + method);
                                }
                            }
                            Class<?> eventType = parameterTypes[0];
                            methodKeyBuilder.setLength(0);
                            methodKeyBuilder.append(methodName);
                            methodKeyBuilder.append('>').append(eventType.getName());
                            String methodKey = methodKeyBuilder.toString();
                            if (eventTypesFound.add(methodKey)) {
                                // Only add if not already found in a sub class
                //封装SubscriberMethod并加入到subscriberMethods中;
                                subscriberMethods.add(new SubscriberMethod(method, threadMode, eventType));
                            }
                        }
                    } else if (!skipMethodVerificationForClasses.containsKey(clazz)) {
                        Log.d(EventBus.TAG, "Skipping method (not public, static or abstract): " + clazz + "."
                                + methodName);
                    }
                }
            }
        //这里将父类重新曲循环;
            clazz = clazz.getSuperclass();
        }
        if (subscriberMethods.isEmpty()) {
            throw new EventBusException("Subscriber " + subscriberClass + " has no public methods called "
                    + ON_EVENT_METHOD_NAME);
        } else {
        //加入缓存;
            synchronized (methodCache) {
                methodCache.put(key, subscriberMethods);
            }
            return subscriberMethods;
        }
    }





    一些代码解释我已经添加到了代码中,希望对大家理解代码有所帮助。再让我们回到register方法中看一下第二步for()循环每一个得到的符合要求的以“OnEvent”开头的方法,上代码:
for (SubscriberMethod subscriberMethod : subscriberMethods) {
            subscribe(subscriber, subscriberMethod, sticky, priority);
        }

    在for循环中调用了subscribe方法并传入了上下文对象、我们得到的众多OnEvent方法中的每一个、是否粘性、优先级;看详细方法:
<span style="font-size:18px;">private void subscribe(Object subscriber, SubscriberMethod subscriberMethod, boolean sticky, int priority) {
        Class<?> eventType = subscriberMethod.eventType;
    //subscriptionsByEventType缓存了所有事件的一个是个Map,key:eventType;value:CopyOnWriteArrayList<Subscription> ;这就是EventBus存储Event方法的地方;
    //用到了CopyWriteArrayList类,不懂得可以去看一下;
    //得到所有订阅了该事件的对象;
        CopyOnWriteArrayList<Subscription> subscriptions = subscriptionsByEventType.get(eventType);
    //封装新的订阅;
        Subscription newSubscription = new Subscription(subscriber, subscriberMethod, priority);
        if (subscriptions == null) {
            subscriptions = new CopyOnWriteArrayList<Subscription>();
    //当前对象没有订阅则加入Map中;
            subscriptionsByEventType.put(eventType, subscriptions);
        } else {
    //是否已经订阅
            if (subscriptions.contains(newSubscription)) {
                throw new EventBusException("Subscriber " + subscriber.getClass() + " already registered to event "
                        + eventType);
            }
        }

        // Starting with EventBus 2.2 we enforced methods to be public (might change with annotations again)
        // subscriberMethod.method.setAccessible(true);

        int size = subscriptions.size();
        for (int i = 0; i <= size; i++) {
    //通过优先级判断添加顺序;优先级越高越靠前(优先级作用);
            if (i == size || newSubscription.priority > subscriptions.get(i).priority) {
                subscriptions.add(i, newSubscription);
                break;
            }
        }
    //通过上下文对象得到所有的已订阅对象列表;根据subscriber存储它所有的eventType;
    //不是核心代码,typesBySubscriber只在判断是否订阅跟取消订阅时用到;
        List<Class<?>> subscribedEvents = typesBySubscriber.get(subscriber);
        if (subscribedEvents == null) {
            subscribedEvents = new ArrayList<Class<?>>();
            typesBySubscriber.put(subscriber, subscribedEvents);
        }
        subscribedEvents.add(eventType);
    //判断sticky;如果为true,从stickyEvents中根据eventType去查找有没有stickyEvent,如果有则立即发布去执行。
    //stickyEvent其实就是我们post时的参数。postToSubscription这个方法,我们在post的时候会介绍。
        if (sticky) {
            Object stickyEvent;
            synchronized (stickyEvents) {
                stickyEvent = stickyEvents.get(eventType);
            }
            if (stickyEvent != null) {
                // If the subscriber is trying to abort the event, it will fail (event is not tracked in posting state)
                // --> Strange corner case, which we don't take care of here.
                postToSubscription(newSubscription, stickyEvent, Looper.getMainLooper() == Looper.myLooper());
            }
        }
    }</span>





到现在整个注册流程就完了,总结一下:register 函数中会先根据订阅者类名去 subscriberMethodFinder 中查找当前订阅者所有事件响应函数,然后循环每一个事件响应函数,依次执行下面的 subscribe 函数:首先扫描了所有的方法,

subscribe 函数分三步

第一步:通过 subscriptionsByEventType 得到该事件类型所有订阅者信息队列,根据优先级将当前订阅者信息插入到订阅者队列 subscriptionsByEventType 中;

第二步:在 typesBySubscriber 中得到当前订阅者订阅的所有事件队列,将此事件保存到队列 typesBySubscriber 中,用于后续取消订阅;

第三步:检查这个事件是否是 Sticky 事件,如果是则从 stickyEvents 事件保存队列中取出该事件类型最后一个事件发送给当前订阅者。

擦,下午1点了,还没吃饭,算了,弄完再说吧。接着来...

2.发布流程。
EventBus.getDefault().Post(new EventOB());
先看流程图

   上源码:
<span style="font-size:18px;">public void post(Object event) {
        PostingThreadState postingState = currentPostingThreadState.get();//得到当前线程状态及相关参数存储类;
        List<Object> eventQueue = postingState.eventQueue;
        eventQueue.add(event);//将event保存到了当前线程中变量PostingThreadState的eventQueue中

        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 {//遍历队列中的所有的event,调用postSingleEvent(eventQueue.remove(0), postingState)方法。
                while (!eventQueue.isEmpty()) {
                    postSingleEvent(eventQueue.remove(0), postingState);//发布单个事件;
                }
            } finally {
                postingState.isPosting = false;
                postingState.isMainThread = false;
            }
        }
    }</span>


currentPostingThreadState是一个ThreadLocal类型的,它的作用大家可以去看一下,里面存储了PostingThreadState;PostingThreadState包含了一个eventQueue和一些标志位。下面接着看PostSingleEvent方法,
<span style="font-size:18px;">private void postSingleEvent(Object event, PostingThreadState postingState) throws Error {
        Class<?> eventClass = event.getClass();
        boolean subscriptionFound = false;
        if (eventInheritance) {//是否支持继承;
            List<Class<?>> eventTypes = lookupAllEventTypes(eventClass);//得到事件的所有类型;包括父类和接口的Class类型;主要用于匹配。
            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));
            }
        }
    }</span>

如果在支持继承的前提下,得到了event对应的每种类型,通过for循环去调用PostSingleEventForEventType方法,我们看看她在里面做了哪些操作;
<span style="font-size:18px;">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参数;
                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;
    }</span>





     可以看到,在这里他通过event从保存了我们所有信息的subscriptionsByEventType中得到我们所有订阅当前事件的所有对象,并for循环对每一个对象调用postToSbuscription()方法,其中赋值了部分postingState参数;下面继续深究postToSubscription()方法;我们传入了订阅了当前事件的对象、事件本身、发布是否在主线程中。
<span style="font-size:18px;">private void postToSubscription(Subscription subscription, Object event, boolean isMainThread) {
        switch (subscription.subscriberMethod.threadMode) {//通过threadMode判断我们要在哪个线程中调用订阅者处理方法;

            case PostThread:
                invokeSubscriber(subscription, event);
                break;
            case MainThread://如果是主线程直接发布,否则调用mainThreadPoster.enqueue方法,方法内部通知主线程的 Handler 发送消息在主线程中处理
                if (isMainThread) {
                    invokeSubscriber(subscription, event);
                } else {
                    mainThreadPoster.enqueue(subscription, event);
                }
                break;
            case BackgroundThread:
                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);
        }
    }</span>


看invokeSubscriber方法:
<span style="font-size:18px;"> 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);
        }
    }</span>


可以看到在invokeSubscriber()方法中用到了反射方式调用订阅者中对应的onEvent*()方法。其实mainThreadPoster、BackgroundThread、asyncPoster中最后都是调用了这个方法来完成对应方法的调用。

case MainThread:
首先去判断当前如果是UI线程,则直接调用;否则: mainThreadPoster.enqueue(subscription, event);把当前的方法加入到队列,然后直接通过handler去发送一个消息,在handler的handleMessage中,去执行我们的方法。说白了就是通过Handler去发送消息,然后执行的。

case BackgroundThread:
如果当前非UI线程,则直接调用;如果是UI线程,则将任务加入到后台的一个队列,最终由Eventbus中的一个线程池去调用
executorService = Executors.newCachedThreadPool();。

case Async:将任务加入到后台的一个队列,最终由Eventbus中的一个线程池去调用;线程池与BackgroundThread用的是同一个。

BackgroundThread中的任务,一个接着一个去调用,中间使用了一个布尔型变量handlerActive进行的控制。Async则会动态控制并发。
好了,我们的发布就介绍到这里。

3.另一种发布。postSticky(Object event); 介绍了register和post;大家获取还能想到一个词sticky,在register中,如何sticky为true,会去stickyEvents去查找事件,然后立即去post;那么这个stickyEvents何时进行保存事件呢?其实evevntbus中,除了post发布事件,还有一个方法也可以:

public void postSticky(Object event) {
        synchronized (stickyEvents) {
            stickyEvents.put(event.getClass(), event);
        }
        // Should be posted after it is putted, in case the subscriber wants to remove immediately
        post(event);
    }
这个方法就是再调用post方法前把方法存储到stickyEvents中去了。

4.注销订阅EventBus.getDefault().unregister(this); 看源码:
public synchronized void unregister(Object subscriber) {
        List<Class<?>> subscribedTypes = typesBySubscriber.get(subscriber);
        if (subscribedTypes != null) {
            for (Class<?> eventType : subscribedTypes) {
                unubscribeByEventType(subscriber, eventType);
            }
            typesBySubscriber.remove(subscriber);
        } else {
            Log.w(TAG, "Subscriber to unregister was not registered before: " + subscriber.getClass());
        }
    }
首先从typesBySubscriber中通过上下文对象得到当前类订阅的所有事件,再for循环每一个事件调用unubscribeByEventType(subscriber, eventType);循环完以后从typesBySubscriber中删除保存的对象。看unubscribeByEventType()方法:
<span style="font-size:18px;">private void unubscribeByEventType(Object subscriber, Class<?> eventType) {
        List<Subscription> subscriptions = subscriptionsByEventType.get(eventType);
        if (subscriptions != null) {
            int size = subscriptions.size();
            for (int i = 0; i < size; i++) {
                Subscription subscription = subscriptions.get(i);
                if (subscription.subscriber == subscriber) {
                    subscription.active = false;
                    subscriptions.remove(i);
                    i--;
                    size--;
                }
            }
        }
    }</span>

在这里我们再次看到了subscriptionsByEventType,通过eventType得到订阅了本事件的所有类集合,及subscriptions。在从subscriptions得到每一个循环对比,如果是当前类,则从subscriptions中将其删除掉。完成取消注册订阅。好了源码就跟大家介绍到这里。下边看一下辅助方面的东西。

五、EventBus主要成员变量含义

1. defaultInstance 默认的 EventBus实例,根据 EventBus.getDefault() 函数得到。

2. DEFAULT_BUILDER 默认的 EventBus Builder。

3. eventTypesCache 事件对应类型及其父类和实现的接口的缓存,以 eventType为 key,元素为 Object的 ArrayList为 Value,Object对象为 eventType的父类或接口。 4. subscriptionsByEventType 事件订阅者的保存队列,以 eventType为 key,元素为 Subscription 的 ArrayList 为 Value,其中 Subscription 为订阅者信息,由 subscriber, subscriberMethod, priority 构成。

5. typesBySubscriber 订阅者订阅的事件的保存队列,以 subscriber为 key,元素为 eventType的 ArrayList为 Value。

6. stickyEvents Sticky事件保存队列,以 eventType为 key,event为元素,由此可以看出对于同一个 eventType最多只会有一个 event存在。

7. currentPostingThreadState 当前线程的 post信息,包括事件队列、是否正在分发中、是否在主线程、订阅者信息、事件实例、是否取消。

8. mainThreadPoster 、 backgroundPoster 、 asyncPoster 事件主线程处理者、事件 Background 处理者、事件异步处理者。

9. subscriberMethodFinder 订阅者响应函数信息存储和查找类。

10. executorService 异步和 BackGround处理方式的线程池。

11. throwSubscriberException 当调用事件处理函数异常时是否抛出异常,默认为 false,建议通过

EventBus.builder().throwSubscriberException(true).installDefaultEventBus()打开。

12. logSubscriberExceptions 当调用事件处理函数异常时是否打印异常信息,默认为 true。

13. logNoSubscriberMessages 当没有订阅者订阅该事件时是否打印日志,默认为 true。

14. sendSubscriberExceptionEvent 当调用事件处理函数异常时是否发送 SubscriberExceptionEvent事件,若此开关打开,订阅者可通过

15. sendNoSubscriberEvent 当没有事件处理函数对事件处理时是否发送NoSubscriber Event事件,若此开关打开,订阅者可通过

16. eventInheritance 是否支持事件继承,默认为 true。

六、涉及到的类介绍 1.EventBusBuilder.java

跟一般 Builder类似,用于在需要设置参数过多时构造 EventBus。包含的属性也是 EventBus的一些设置参数,意义见 4.2.1 EventBus.java 的介绍,build函数用于新建 EventBus 对象,installDefaultEventBus函数将当前设置应用于 Default EventBus。

2.SubscriberMethodFinder.java

订阅者响应函数信息存储和查找类,由 HashMap缓存,以 ${subscriberClassName}为 key,SubscriberMethod对象为元素的 ArrayList为 value。findSubscriberMethods函数用于查找订阅者响应函数,如果不在缓存中,则遍历自己的每个函数并递归父类查找,查找成功后保存到缓存中。

3.SubscoberMethod.java

订阅者事件响应函数信息,包括响应方法、线程 Mode、事件类型以及一个用来比较 SubscriberMethod是否相等的特征值 methodString共四个变量,其中 methodString为${methodClassNmae}#${methodName}(${eventTypeClassName}。


4.Subscription.java

订阅者信息,包括 subscriber对象、事件响应方法 SubscriberMethod、优先级 priority.

5.HandlerPoster.java

事件主线程处理,对应 ThreadMode.MainThread 。继承自 Handler,enqueue函数将事件放到队列中,并利用 handler 发送message,handleMessage函数从队列中取事件,invoke事件响应函数处理。

6.AsyncPoster.java

事件异步线程处理,对应 ThreadMode.Async ,继承自 Runnable。enqueue函数将事件放到队列中,并调用线程池执行当前任务,在 run 函数从队列中取事件,invoke事件响应函数处理。

7.BackgroundPoster.java

事件 Background处理,对应 ThreadMode.BackgroundThread ,继承自 Runnable。enqueue函数将事件放到队列中,并调用线程池执行当前任务,在 run函数从队列中取事件,invoke事件响应函数处理,与 AsyncPoster.java不同的是这里会循环等待 run,尚未想清楚原因。

8.PendingPost.java

订阅者和事件信息实体类,并含有同一队列中指向下一个对象的指针。通过缓存存储不用的对象,减少下次创建的性能消耗。

9.PendingPostQueue.java

通过 head和 tail指针维护一个 PendingPost 队列。HandlerPoster、AsyncPoster、BackgroundPoster都包含一个此队列实例,表示各自的订阅者及事件信息队列,在事件到来时进入队列,处理时从队列中取出一个元素进行处理。

10.SubscriberExceptionEvent.java

当调用事件处理函数异常时发送的 EventBus内部自定义事件,通过 post发送,订阅者可自行订阅这类事件进行处理。

11.NoSubscriberEvent.java

当没有事件处理函数对事件处理时发送的EventBus内部自定义事件,通过 post发送,订阅者可自行订阅这类事件进行处理。

12.EventBusException.java

封装于RuntimeException之上的 Exception,只是覆盖构造函数,相当于一个标记,标记是属于 EventBus的 Exception。

13.4.2.14 ThreadMode.java

线程 Mode枚举类,表示事件响应函数执行线程信息,包括ThreadMode.PostThread 、 ThreadMode.MainThread 、ThreadMode.BackgroundThread 、 ThreadMode.Async 四种。
好了,刚刚开始在CSDN上边发表文章,还不太会用,不好意思,有些地方可能说的不是很清楚,请大家谅解。总算完了,也两点半了,收拾收拾去吃饭了,擦,还真饿了!!





刚刚创建了132079212,希望能共同学习,非诚勿扰!


版权声明:本文为博主原创文章,未经博主允许不得转载。

标签: android

热门推荐