EventBus源码分析

2019-02-19  本文已影响0人  瓦雷
问题1:EventBus可以创建多个实例吗?
/**
     * Creates a new EventBus instance; each instance is a separate scope in which events are delivered. To use a
     * central bus, consider {@link #getDefault()}.
     */
    public EventBus() {
        this(DEFAULT_BUILDER);
    }

这里会发现EventBus的构造方法是公有的,也就是说我们自己可以自己new一个EventBus的实例,当然EventBus也提供了EventBusBuilder供我们构造使用。这里特意把构造方法的注释放了上来,大概翻译一下吧。

创建一个EventBus实例,每一个实例的事件传递都在自己的实例范围,如果想统一管理,可以使用getDefault()方法。
这里通过注释我们就可以解释第五个问题了,当然只是从注释层面,EventBus是可以创建多个实例的,并且多个实例的发送的事件是互不干扰的

再看下 findSubscriberMethods() 这个方法,会通过类对象的 class 去解析这个类中的所有 Subscribe 注解方法的所有属性值,一个注解方法对应一个 SubscriberMethod 对象,包括 threadMode,priority,sticky,eventType,methodString。

2、源码分析

首先来看register

 //subscriber 传入的就是当前注册的Activity
    public void register(Object subscriber) {
        Class<?> subscriberClass = subscriber.getClass();
        //查找传入的Activity中一共有多少个含有@Subscribe注解的监听方法,有几个@Subscribe注解subscriberMethods的size就为几
        List<SubscriberMethod> subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass);
        synchronized (this) {
            for (SubscriberMethod subscriberMethod : subscriberMethods) {
                // subsciber 对 List<SubscriberMethod> 中每个 SubscriberMethod 进行订阅
                subscribe(subscriber, subscriberMethod);
            }
        }
    }

说明下SubscriberMethod这个类,类中有个参数eventType指的就是事件类型,即调用post("eventType")方法中传入的参数,也是@Subscribe注解的接收数据的方法中的入参,以下是debug中日志信息,很好的说明了一切:

image.png

再来看看Subscription这个类,可以理解成订阅者信息类

//指的是当前订阅者的类
final Object subscriber;
final SubscriberMethod subscriberMethod;

考以下几个问题:

对于同一个 Event,当前类对该对象使用了多个方法进行了多次订阅,那么如果该 Event 被发射的时候,当前类会如何调用这些方法?
对于同一个 Event,父类对该对象进行了一次订阅,子类重写该订阅方法,那么如果该 Event 被发射的时候,父类子类当中会如何处理这些方法?

1、会的
2、会调用子类的,不会调用父类的

注册完之后就需要做订阅操作,subscribe

// Must be called in synchronized block
    private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) {
        Class<?> eventType = subscriberMethod.eventType;
        Subscription newSubscription = new Subscription(subscriber, subscriberMethod);
        //说明1
        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;
            }
        }
        //说明2
        List<Class<?>> subscribedEvents = typesBySubscriber.get(subscriber);
        if (subscribedEvents == null) {
            subscribedEvents = new ArrayList<>();
            typesBySubscriber.put(subscriber, subscribedEvents);
        }
        subscribedEvents.add(eventType);

     // 省略 sticky 事件

说明1中:subscriptionsByEventType 是一个Map<Class<?>, CopyOnWriteArrayList<Subscription>>类型,key是eventType,value是订阅者集合

说明2中:typesBySubscriber 是一个Map<Object, List<Class<?>>>类型
key为订阅者类,value为eventType集合,主要是在关闭界面时反注册的时候使用

上一篇下一篇

猜你喜欢

热点阅读