EventBus源码解析02-订阅者注册

接着,我们来看EventBus的订阅过程

public void register(Object subscriber) {
    Class<?> subscriberClass = subscriber.getClass();
    List<SubscriberMethod> subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass);
    synchronized (this) {
        for (SubscriberMethod subscriberMethod : subscriberMethods) {
            subscribe(subscriber, subscriberMethod);
        }
    }
}

这里,首先获取订阅者的class,接着,通过subscriberMethodFinder.findSubscriberMethods来查找订阅者的方法。

List<SubscriberMethod> findSubscriberMethods(Class<?> subscriberClass) {
    //从缓存中获取
    List<SubscriberMethod> subscriberMethods = METHOD_CACHE.get(subscriberClass);
    if (subscriberMethods != null) {
        return subscriberMethods;
    }

    //ignoreGenerateIndex为true会优先使用编译时Index来查找,为false将忽略使用Index来查找
    if (ignoreGeneratedIndex) {
        //通过反射来获取方法集合
        subscriberMethods = findUsingReflection(subscriberClass);
    } else {
        //优先通过Index来获取方法集合
        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;
    }
}  

一般通过getDefault()获取的EventBus对象,builder构建是ignoreGenerateIndex为false,故会调用findUsingInfo()

private List<SubscriberMethod> findUsingInfo(Class<?> subscriberClass) {
    //从缓存数组中获取(如果存在的话,不存在的话将新new一个)
    FindState findState = prepareFindState();
    //将findstate的subscriberClass和clazz变量赋值为subscriberClass
    findState.initForSubscriber(subscriberClass);
    while (findState.clazz != null) {
        //从Index中获取subscriberInfo
        findState.subscriberInfo = getSubscriberInfo(findState);
        如果subscriberInfo存在
        if (findState.subscriberInfo != null) {
            SubscriberMethod[] array = findState.subscriberInfo.getSubscriberMethods();
            for (SubscriberMethod subscriberMethod : array) {
                if (findState.checkAdd(subscriberMethod.method, subscriberMethod.eventType)) {
                    //将符合条件的方法添加到findState的集合中
                    findState.subscriberMethods.add(subscriberMethod);
                }
            }
        } else {
            //说明Index中不存在,通过反射来查找Method
            findUsingReflectionInSingleClass(findState);
        }
        //移动到父类继续查找
        findState.moveToSuperclass();
    }
    return getMethodsAndRelease(findState);
}  

findUsingInfo中,会先从Inex中查找Method,如果Index中不存在,则通过反射来查找,最终会添加到findState的subscriberMethods集合中并返回。

再来看下findUsingReflectionInSingleClass,可以看到,主要就是通过反射遍历所有的Method,找到有Subscribe注解的Method,将其加入到subscriberMethods列表中返回。

  private void findUsingReflectionInSingleClass(FindState findState) {
    Method[] methods;
    try {
        // This is faster than getMethods, especially when subscribers are fat classes like Activities
        methods = findState.clazz.getDeclaredMethods();
    } catch (Throwable th) {
        // Workaround for java.lang.NoClassDefFoundError, see https://github.com/greenrobot/EventBus/issues/149
        methods = findState.clazz.getMethods();
        findState.skipSuperClasses = true;
    }
    for (Method method : methods) {
        int modifiers = method.getModifiers();
        if ((modifiers & Modifier.PUBLIC) != 0 && (modifiers & MODIFIERS_IGNORE) == 0) {
            Class<?>[] parameterTypes = method.getParameterTypes();
            if (parameterTypes.length == 1) {
                Subscribe subscribeAnnotation = method.getAnnotation(Subscribe.class);
                if (subscribeAnnotation != null) {
                    Class<?> eventType = parameterTypes[0];
                    if (findState.checkAdd(method, eventType)) {
                        ThreadMode threadMode = subscribeAnnotation.threadMode();
                        findState.subscriberMethods.add(new SubscriberMethod(method, eventType, threadMode,
                                subscribeAnnotation.priority(), subscribeAnnotation.sticky()));
                    }
                }
            } else if (strictMethodVerification && method.isAnnotationPresent(Subscribe.class)) {
                String methodName = method.getDeclaringClass().getName() + "." + method.getName();
                throw new EventBusException("@Subscribe method " + methodName +
                        "must have exactly 1 parameter but has " + parameterTypes.length);
            }
        } else if (strictMethodVerification && method.isAnnotationPresent(Subscribe.class)) {
            String methodName = method.getDeclaringClass().getName() + "." + method.getName();
            throw new EventBusException(methodName +
                    " is a illegal @Subscribe method: must be public, non-static, and non-abstract");
        }
    }
}  

获得这个类(及其父类)符合的方法后,会将其放到缓存列表METHOD_CACHE中。

接着,回到register方法,获取subscriberMethods列表后,会遍历这个列表,并调用subscribe()方法

for (SubscriberMethod subscriberMethod : subscriberMethods) {
    subscribe(subscriber, subscriberMethod);
}  

在subscribe()方法中,最终完成订阅

// Must be called in synchronized block
private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) {
    Class<?> eventType = subscriberMethod.eventType;
    //创建被观察者对象
    Subscription newSubscription = new Subscription(subscriber, subscriberMethod);
    //根据类名获取相应的Subscription列表
    CopyOnWriteArrayList<Subscription> subscriptions = subscriptionsByEventType.get(eventType);
    if (subscriptions == null) {
        //subscriptions列表不存在,则创建并添加到subscriptionsByEventType
        subscriptions = new CopyOnWriteArrayList<>();
        subscriptionsByEventType.put(eventType, subscriptions);
    } else {
        if (subscriptions.contains(newSubscription)) {
            //如果列表中已包含该Subscription,则抛出异常
            throw new EventBusException("Subscriber " + subscriber.getClass() + " already registered to event "
                    + eventType);
        }
    }

    int size = subscriptions.size();
    //根据priority(优先级)添加Subscription到相应的位置
    for (int i = 0; i <= size; i++) {
        if (i == size || subscriberMethod.priority > subscriptions.get(i).subscriberMethod.priority) {
            subscriptions.add(i, newSubscription);
            break;
        }
    }
    //将eventType存储到subscriber的typesBySubscriber列表中
    List<Class<?>> subscribedEvents = typesBySubscriber.get(subscriber);
    if (subscribedEvents == null) {
        subscribedEvents = new ArrayList<>();
        typesBySubscriber.put(subscriber, subscribedEvents);
    }
    subscribedEvents.add(eventType);

    //如果是sticky (粘性事件)
    if (subscriberMethod.sticky) {
        //是否考虑所有子类,为true,子类也将能接收到
        //从EventBusBuilder可知,eventInheritance默认为true.
        if (eventInheritance) {
            // Existing sticky events of all subclasses of eventType have to be considered.
            // Note: Iterating over all events may be inefficient with lots of sticky events,
            // thus data structure should be changed to allow a more efficient lookup
            // (e.g. an additional map storing sub classes of super classes: Class -> List<Class>).
            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);
        }
    }
}

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

总结

EventBus的订阅过程主要就是通过Index或者反射遍历@Subscribe注解,找到该类(及其父类,这个默认为true,可配置)所有的订阅方法,然后逐个进行subscribe(),添加到相应的集合中,供后续使用。
如果是sticky事件,则从sticky的Set集合中取出相应的事件,如果事件符合当前这个订阅方法,则立即执行。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

氦客

你的鼓励是我创作最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值