EventBus流程及原理

EventBus原理

设计模式:单例模式、建造者模式、观察者模式

单例:
image
建造者:
image

register:

流程图:
register
源码:
public void register(Object subscriber) {

// 用 subscriberMethodFinder 提供的方法,找到在 subscriber 这个类里面,订阅的内容。

Class subscriberClass = subscriber.getClass();

    List subscriberMethods =subscriberMethodFinder.findSubscriberMethods(subscriberClass);

    synchronized (this) {

for (SubscriberMethod subscriberMethod : subscriberMethods) {

// 遍历这些方法,subscribe 这些事件

subscribe(subscriber, subscriberMethod);

        }

}

}
subscribe():生成3个集合类
private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) {
    //获取subsrciberMethod传递的自定义EventType参数的运行时的类
    Class eventType = subscriberMethod.eventType;
    //Subscription用于绑定subscriber和sucriberMethod,一个订阅者可以有多个subscriberMethod
    Subscription newSubscription = new Subscription(subscriber, subscriberMethod);
    //根据EventType的运行时类取到该类所有的subscriptioins,subscriptionsByEventType是HashMap中的key
    CopyOnWriteArrayList subscriptions = subscriptionsByEventType.get(eventType);
    if (subscriptions == null) {
         subscriptions = new CopyOnWriteArrayList<>();
         //若根据EventType找不到subscriptions,则eventType作key,subscriptions作value添加到subscriptionByEventType中。
         subscriptionsByEventType.put(eventType, subscriptions);
    } else {
         if (subscriptions.contains(newSubscription)) {
         //已经存在newSubscription,抛出异常该订阅者已经注册,不可重复注册同一个subscriber
             throw new EventBusException("Subscriber " + subscriber.getClass() + " already registered to event "
                     + eventType);
         }
    }

    int size = subscriptions.size();
    for (int i = 0; i <= size; i++) {
        //循环subscriptions,根据标记优先级的priority从高到低,将新的subscription插入到subscriptions中
        if (i == size || subscriberMethod.priority > subscriptions.get(i).subscriberMethod.priority) {
            subscriptions.add(i, newSubscription);
            break;
        }
    }
    //typesBySubscriber是一个HashMap,根据subscriber做key,获取该subscriber对应的所有的订阅事件的类型
    List> subscribedEvents = typesBySubscriber.get(subscriber);
      if (subscribedEvents == null) {
          subscribedEvents = new ArrayList<>();
          //该订阅者之前的订阅事件类型列表为空,则将当前订阅类型添加到typesBySubscriber中
          typesBySubscriber.put(subscriber, subscribedEvents);
      }
    subscribedEvents.add(eventType);
    //如果该方法被标识为sticky事件
    if (subscriberMethod.sticky) {
         if (eventInheritance) { eventInheritance标识是否考虑EventType的类层次结构
              //循环所有的sticky黏性事件
              Set, Object>> entries = stickyEvents.entrySet();
              for (Map.Entry, Object> entry : entries) {
                  Class candidateEventType = entry.getKey();
                  //如果当前事件是其他事件的同类型的或者是他们的父类
                  if (eventType.isAssignableFrom(candidateEventType)) {
                     Object stickyEvent = entry.getValue();
                     heckPostStickyEventToSubscription(newSubscription, stickyEvent);
                  }
              }
         } else {
             Object stickyEvent = stickyEvents.get(eventType);
             checkPostStickyEventToSubscription(newSubscription, stickyEvent);
         }
    }
}
  1. Map<Class<?>,CopyOnWriteArrayList<Subscription>> subscriptionByEventType -> Key:Event,Value:Subscribe集合,当发送这个Event时,可在Map中找到相应的Subscriber集合,将订阅方法可接收时间类型和对应的Subscription集合保存到subscriptionsByEventType中去。

2. Map<Object,List<Class<?>>> typeBySubscriber -> Key:Subscriber,Value:Event,当注册和反注册时,都会操作typesBySubscriber,将注册类对象和注册类中订阅事件方法的参数类型集合保存到typesBySubscriber。

3. Map, Object>stickyEvents -> 如果是粘性事件subscriberMethod.sticky=true,则从stickyEvent中取出对应类型时间,用迭代器一一进行执行订阅事件的方法。

订阅的方法信息
public SubscriberMethod(String methodName, Class<?> eventType, ThreadMode threadMode,
                                int priority, boolean sticky) {
        this.methodName = methodName;
        this.threadMode = threadMode;
        this.eventType = eventType;
        this.priority = priority;
        this.sticky = sticky;
    }
findSubscriberMethods 这个方法是实现 EventBus 的核心代码,这里面包含了 EventBus 隐式定义的交互协议。从这个方法里面,可以看到如何争取地使用EventBus。
 List<SubscriberMethod> findSubscriberMethods(Class<?> subscriberClass) { {

// 如果这个 Class 对应的方法被缓存,直接返回。

List subscriberMethods =METHOD_CACHE.get(subscriberClass);

    if (subscriberMethods !=null) {

return subscriberMethods;

    }

//ignoreGeneratedIndex默认为false,是否从索引勒种取出当前注册类对应的事件订阅方法信息

if (ignoreGeneratedIndex) {

subscriberMethods = findUsingReflection(subscriberClass);//使用反射去查找

    }else {

subscriberMethods = findUsingInfo(subscriberClass);//使用索引去查找

    }

if (subscriberMethods.isEmpty()) {//空就抛异常,不空加进缓存中

throw new EventBusException("Subscriber " + subscriberClass

+" and its super classes have no public methods with the @Subscribe annotation");

    }else {

METHOD_CACHE.put(subscriberClass, subscriberMethods);

        return subscriberMethods;

    }

}


post&postSticky:

流程图:
post&postSticky
postSticky:
/**

* Posts the given event to the event bus and holds on to the event (because it is sticky). The most recent sticky

* event of an event's type is kept in memory for future access by subscribers using {@link Subscribe#sticky()}.

*/

public void postSticky(Object event) {

    synchronized (stickyEvents) {

        stickyEvents.put(event.getClass(), event);//加入粘性事件stickyEvents:Map中

    }

  // Should be posted after it is putted, in case the subscriber wants to remove immediately

    post(event);

}
######post:
/** Posts the given event to the event bus. */

public void post(Object event) {

  //从currentPostingThreadState:ThreadLocal中获取发送线程的状态

    PostingThreadState postingState =currentPostingThreadState.get();

    List eventQueue = postingState.eventQueue; //从获取发送线程中队列

    eventQueue.add(event);//将事件加入到发送线程中队列

    if (!postingState.isPosting) {//如果没有发送就开始去发送

        postingState.isMainThread = isMainThread();

        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;

        }

    }

}

private void postSingleEvent(Object event, PostingThreadState postingState) throws Error {

        /*获取事件的Class,所有事件的Class对应的订阅者列表在register的时候是已经保存了的*/

        Class<?> eventClass = event.getClass();

        /*根据事件的Class找到订阅者的标志状态,初始化为false*/

        boolean subscriptionFound = false;

        /*

        * 比如 A extends B implements C  发布者post(A),那么找订阅者的时候不仅要找订阅了事件A的订阅者

        * 还要找订阅了B和C的订阅者*/

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

     }
   }
}

前边说过了EventBus维护了两个重要的map。其中一个就是事件的Class到能处理此事件的所有订阅者列表的map,因此不仅要把事件的Class存入map中的订阅者列表,还要把事件的所有父类和所有实现的接口的Class存入订阅者列表。下边是找到某个类所有父类和所有实现接口的方法:

/** Looks up all Class objects including super classes and interfaces. Should also work for interfaces. */

    /*找到事件的所有父类和实现的接口,以Class列表的形式返回*/

    private List<Class<?>> lookupAllEventTypes(Class<?> eventClass) {

        /*private static final Map<Class<?>, List<Class<?>>> eventTypesCache = new HashMap<Class<?>, List<Class<?>>>();*/

        synchronized (eventTypesCache) {

            /*查看缓存,看能否命中*/

            List<Class<?>> eventTypes = eventTypesCache.get(eventClass);

            /*缓存不命中*/

            if (eventTypes == null) {

                /*创建事件类型列表*/

                eventTypes = new ArrayList<Class<?>>();

                Class<?> clazz = eventClass;

                /*getSuperclass()返回null的情况:Class表示的类为Object、基本数据类型、接口或者void*/

                while (clazz != null) {

                    eventTypes.add(clazz);

                    /*把接口对应的Class也添加进Class列表

                    * clazz.getInterfaces():返回clazz表示的类直接实现的接口的Class列表,不包括间接实现的接口

                    * */

                    addInterfaces(eventTypes, clazz.getInterfaces());

                    /** public Class<? super T> getSuperclass() :

                    * Returns the Class object which represents the superclass of the

                    * class represented by this  Class. If this  Class represents

                    * the Object class, a primitive type, an interface or void then the

                    * method returns null. If this Class represents an array

                    * class then the  Object class is returned.

                    */

                    clazz = clazz.getSuperclass();

                }

                /*找到一个事件的所有父类和所有实现接口的Class挺复杂的,循环加递归的,还是加入缓存机制提高性能吧*/

                eventTypesCache.put(eventClass, eventTypes);

            }

            return eventTypes;

        }

    }

    /** Recurses through super interfaces. 获取某个类直接实现的所有接口,包括间接实现的

    * @param eventTypes

    * @param interfaces*/

    static void addInterfaces(List<Class<?>> eventTypes, Class<?>[] interfaces) {

        /*对这个类直接实现的每个接口开始遍历*/

        for (Class<?> interfaceClass : interfaces) {

            /*如果这个接口还没有添加到列表接把他添加到列表*/

            if (!eventTypes.contains(interfaceClass)) {

                eventTypes.add(interfaceClass);

                /*把这个接口所直接实现的所有接口的Class也添加进列表 递归调用*/

                addInterfaces(eventTypes, interfaceClass.getInterfaces());

            }

        }

    }
最后调用
private void checkPostStickyEventToSubscription(Subscription newSubscription, Object stickyEvent) {
        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());
        }
    }

private void postToSubscription(Subscription subscription, Object event, boolean isMainThread) {
       //根据@subscriber中threadMode进行区分,POSTING为当前线程执行,
       //MAIN为主线程,BACKGROUND为子进程,ASYNC为异步执行。
       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);
        }
    }

unregister:

流程图:
unregister
源码:
/** Unregisters the given subscriber from all event classes. */
    public synchronized void unregister(Object subscriber) {
        List<Class<?>> subscribedTypes = typesBySubscriber.get(subscriber);
        if (subscribedTypes != null) {
            for (Class<?> eventType : subscribedTypes) {
                unsubscribeByEventType(subscriber, eventType);
            }
            typesBySubscriber.remove(subscriber);
        } else {
            logger.log(Level.WARNING, "Subscriber to unregister was not registered before: " + subscriber.getClass());
        }
    }

/** Only updates subscriptionsByEventType, not typesBySubscriber! Caller must update typesBySubscriber. */
    private void unsubscribeByEventType(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--;
                }
            }
        }
    }

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容