Android开发

EventBus 源码的阅读03 - EventBus 的注册(

2020-11-20  本文已影响0人  __Y_Q

在上篇中, 分析学习了 EventBus 注册过程中的第一步. 就是获取注册类中所有的订阅方法.
下篇主要分析的是在获得所有订阅方法后, 逐个对他们进行订阅.
那么具体是如何进行订阅的呢. 下面直接进入正题.


EventBus.register(Object subscriber)

public void register(Object subscriber) {
    //通过反射获得订阅者的 Class 对象
    Class<?> subscriberClass = subscriber.getClass();
    //通过订阅者 Class 对象找到该对象内所有的订阅方法集合
    List<SubscriberMethod> subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass);
    synchronized (this) {
        //遍历并进行单个方法的订阅
        for (SubscriberMethod subscriberMethod : subscriberMethods) {
            subscribe(subscriber, subscriberMethod);
        }
    }
}

看代码, 在获得 subscriberMethods 集合后, 就开始了遍历整个集合, 并调用了 subscribe(Object subscriber, SubscriberMethod subscriberMethod) 方法. 传入订阅者与订阅者内部的某个订阅方法这两个参数, 准备开始订阅.


2. EventBus.subscribe(subscriber, subscriberMethod)

// Must be called in synchronized block
private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) {
    //分析一
    Class<?> eventType = subscriberMethod.eventType;
    Subscription newSubscription = new Subscription(subscriber, subscriberMethod);
    CopyOnWriteArrayList<Subscription> subscriptions = subscriptionsByEventType.get(eventType);
    //分析二
    if (subscriptions == null) {
        subscriptions = new CopyOnWriteArrayList<>();
        subscriptionsByEventType.put(eventType, subscriptions);
    } else {
        if (subscriptions.contains(newSubscription)) {
            throw new EventBusException("Subscriber " + subscriber.getClass() + " already registered to event "
                    + eventType);
        }
    }
    //分析三
    int size = subscriptions.size();
    for (int i = 0; i <= size; i++) {
        if (i == size || subscriberMethod.priority > subscriptions.get(i).subscriberMethod.priority) {
            subscriptions.add(i, newSubscription);
            break;
        }
    }
    //分析四
    List<Class<?>> subscribedEvents = typesBySubscriber.get(subscriber);
    if (subscribedEvents == null) {
        subscribedEvents = new ArrayList<>();
        typesBySubscriber.put(subscriber, subscribedEvents);
    }
    subscribedEvents.add(eventType);
     //分析 5
    if (subscriberMethod.sticky) {
        if (eventInheritance) {
            Set<Map.Entry<Class<?>, Object>> entries = stickyEvents.entrySet();
            for (Map.Entry<Class<?>, Object> entry : entries) {
                Class<?> candidateEventType = entry.getKey();
                if (eventType.isAssignableFrom(candidateEventType)) {
                    Object stickyEvent = entry.getValue();
                    checkPostStickyEventToSubscription(newSubscription, stickyEvent);
                }
            }
        } else {
            Object stickyEvent = stickyEvents.get(eventType);
            checkPostStickyEventToSubscription(newSubscription, stickyEvent);
        }
    }
}

因为代码过长, 所以讲 subscribe 方法分为两个部分来分析. 第一部分是正常处理流程, 第二部分是粘性事件的处理流程.

开始分析第一部分之前, 再回忆一下在第一章中创建 EventBus 对象中的两个重要的 Map 集合, 以便加深印象, 也更容易加深对本篇内容的理解.
(这里就不再贴图了, 直接以文字描述了. 想看图的可以去 EventBus 源码的阅读01 - EventBus 对象的创建 中查看.)

  • private final Map<Class<?>, CopyOnWriteArrayList<Subscription>> subscriptionsByEventType
    以当前 Event 事件为 key, 以 CopyOnWriteArrayList<Subscription> 列表为 value.
    Subscription 可以理解为一条订阅记录, 这个记录中又包含了两个内容, 一个是包含了订阅这个 Event 事件的 subscriber 订阅者(反射执行对象),一个是 SubscriberMethod. (订阅方法的包装类.)

这个 map 的目的是为了在发送 Event 事件的时候, 以 Event 事件为 key 直接在这个 map 中找到所有订阅了这个事件的 Subscription(订阅记录)列表. 找到列表后, 就可以针对列表内的每一条订阅记录进行发送事件.

  • private final Map<Object, List<Class<?>>> typesBySubscriber
    subscriber 订阅者为 key, 以订阅者中订阅的所有 Event 事件类型列表为 value.

订阅者到事件列表的 map, 这样订阅者向 EventBus 注册与解除注册的时候可以根据订阅者获取该订阅者订阅的所有事件, 对每个事件分别进行操作.






到这里 EventBus 的注册流程分析完了. 总结后大致流程如下:

  1. 根据 EventBus.getDefault().register(this) 中的这个 this, 作为订阅者.
  2. 根据订阅者获取订阅者内部的所有订阅方法.
  3. 接着遍历订阅者内部的所有订阅方法, 进行订阅.
  4. 订阅的时候会先判断是否订阅过这个事件.
  5. 按照优先级将订阅记录加入到 subscriptionsByEventType 的 value 的 list 中
  6. 将当前事件类型加入到订阅者对应的订阅事件列表中 (typesBySubscriber 的 value 的 list 中)
  7. 是否是粘性事件.
  8. 调用 checkPostStickyEventToSubscription 分发事件.
上一篇 下一篇

猜你喜欢

热点阅读