EventBus3.0源码分析(三)

  1. EventBus3.0源码分析(一)两种使用方式
  2. EventBus3.0源码分析(二)
  3. EventBus3.0源码分析(三)
  4. EventBus3.0源码分析(四)

这一篇我们来分析EventBus的register()与unregister()方法。

EventBus.java

public void register(Object subscriber) {
        ......
        // 得到传入对象的类型,如MainActivity.class
        Class<?> subscriberClass = subscriber.getClass();
        // 注释2 根据方法名可知,寻找@Subscribe标记的方法
        List<SubscriberMethod> subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass);
        // 注释3 遍历了上面的方法集合
        synchronized (this) {
            for (SubscriberMethod subscriberMethod : subscriberMethods) {
                //注释4 这里其实是做了粘性事件的分发,这也是粘性事件能够先发送,再注册也能接受到的直接原因,后面详细分析。
                subscribe(subscriber, subscriberMethod);
            }
        }
    }

紧跟注释2,看他是怎么寻找Subscribe方法的:

SubscriberMethodFinder.java

//用来缓存Subscriber方法,使用的线程安全的ConcurrentHashMap
private static final Map<Class<?>, List<SubscriberMethod>> METHOD_CACHE = new ConcurrentHashMap<>();


List<SubscriberMethod> findSubscriberMethods(Class<?> subscriberClass) {
        //key:类类型,如MainActivity.classs
        //value: Subscriber方法列表
        //先去缓存里找,找到直接返回
        List<SubscriberMethod> subscriberMethods = METHOD_CACHE.get(subscriberClass);
        if (subscriberMethods != null) {
            return subscriberMethods;
        }

        // ignoreGeneratedIndex是在SubscriberMethodFinder的构造方法中被赋值的,向上溯源,它的值来自EventBusBuilder,默认为false。
        if (ignoreGeneratedIndex) {
            // 注释1@findSubscriberMethods 直接使用反射获取subscriber方法列表
            subscriberMethods = findUsingReflection(subscriberClass);
        } else {
            // 注释2@findSubscriberMethods 在ADT生成的索引类MyEventBusIndex中的Map缓存中查找
            subscriberMethods = findUsingInfo(subscriberClass);
        }
        // 一个都没找到的话抛出异常
        if (subscriberMethods.isEmpty()) {
            throw new EventBusException("Subscriber " + subscriberClass
                    + " and its super classes have no public methods with the @Subscribe annotation");
        } else {
            // 将查找到的subscriber方法列表,添加到map缓存方便下次使用,需要注意的是这个map和MyEventBusIndex中map的区别,这个map缓存的是当前调用了register()方法的类里的subscriber方法,而MyEventBusIndex中的map缓存的是所有类中的subscriber方法。
            METHOD_CACHE.put(subscriberClass, subscriberMethods);
            // 返回method列表
            return subscriberMethods;
        }
    }

接下来进入注释1@findSubscriberMethods处的方法:

SubscriberMethodFinder.java

private List<SubscriberMethod> findUsingReflection(Class<?> subscriberClass) {
        FindState findState = prepareFindState();
        findState.initForSubscriber(subscriberClass);
        while (findState.clazz != null) {
            //注意这个方法,留一个印象
            findUsingReflectionInSingleClass(findState);
            findState.moveToSuperclass();
        }
        return getMethodsAndRelease(findState);
    }

这里先留个印象暂不往下分析,在上面findSubscriberMethods方法中的else分支中有一种情况也会调用到findUsingReflectionInSingleClass()方法后面一起看。

ok,我们来到注释2@findSubscriberMethods处的方法:

SubscriberMethodFinder.java

    private List<SubscriberMethod> findUsingInfo(Class<?> subscriberClass) {
        //注释1@findUsingInfo,可先看下面对FindState的分析
        FindState findState = prepareFindState();
        //注释2@findUsingInfo 给findState的属性初始化赋值
        findState.initForSubscriber(subscriberClass);
        while (findState.clazz != null) {  //由上行代码可知,findState.clazz不为空,进入while循环    
            //注释3@findUsingInfo
            findState.subscriberInfo = getSubscriberInfo(findState);
            // 在此系列文章第一篇中提到的,使用ADT方式这里就不为空
            if (findState.subscriberInfo != null) {
                //得到subscriberClass类中的所有subscriber方法
                SubscriberMethod[] array = findState.subscriberInfo.getSubscriberMethods();
                 
                for (SubscriberMethod subscriberMethod : array) {
                    //在下面分析checkAdd方法,判断是否符合存储条件
                    if (findState.checkAdd(subscriberMethod.method, subscriberMethod.eventType)) {
                        //添加到订阅方法列表
                        findState.subscriberMethods.add(subscriberMethod);
                    }
                }
            } else { //反射的方式查找subscriber方法,通过遍历的方式将所有@Subscribe注解标记的方法存储到findState.subscriberMethods中,逻辑与上面ADT方式大同小异,就不在深入分析了
                findUsingReflectionInSingleClass(findState);
            }
            //在下面分析此方法
            findState.moveToSuperclass();
        }
        //将收集到的订阅方法列表返回
        return getMethodsAndRelease(findState);
    }

这个方法中反复提到了一个数据结构FindState,它是SubscriberMethodFinder的一个内部类,主要用来存储在查找Subscriber方法过程中产生的一些临时对象。我们可以先看下它的结构:

static class FindState {
        //subscriber方法列表
        final List<SubscriberMethod> subscriberMethods = new ArrayList<>();
        //存储EventType和Method对象的对应关系
        final Map<Class, Object> anyMethodByEventType = new HashMap<>();
        //存储subscriber方法的方法名与方法签名(EventBus自定义规则)
        final Map<String, Class> subscriberClassByMethodKey = new HashMap<>();
        //方法签名
        final StringBuilder methodKeyBuilder = new StringBuilder(128);
        //外部传入的,如MainActivity.class
        Class<?> subscriberClass;
        Class<?> clazz;
        //是否跳过父类
        boolean skipSuperClasses;
        //是一个接口,它的实现类是SimpleSubscriberInfo,即MyEventBusIndex中的map存储的value 对象
        SubscriberInfo subscriberInfo;

        ......

        boolean checkAdd(Method method, Class<?> eventType) {
            // 2 level check: 1st level with event type only (fast), 2nd level with complete signature when required.
            // Usually a subscriber doesn't have methods listening to the same event type.
            //先检查同一个订阅者(如:MainActivity.class)之前是否有相同类型的Event的方法,没有的话,直接返回true,表示可以添加
            Object existing = anyMethodByEventType.put(eventType, method);
            if (existing == null) {
                return true;
            } else {
                //否则看之前存储的这个对象是不是一个Method对象
                if (existing instanceof Method) {
                    if (!checkAddWithMethodSignature((Method) existing, eventType)) {
                        // Paranoia check
                        throw new IllegalStateException();
                    }
                    // Put any non-Method object to "consume" the existing Method
                    anyMethodByEventType.put(eventType, this);
                }
                return checkAddWithMethodSignature(method, eventType);
            }
        }

    
        //这个方法用来判断同一个订阅者(如:MainActivity.class)中,是不是已经存在和当前要注册的method方法名相同且EventType也相同,是则不能添加。
        private boolean checkAddWithMethodSignature(Method method, Class<?> eventType) {
            methodKeyBuilder.setLength(0);
            methodKeyBuilder.append(method.getName());
            methodKeyBuilder.append('>').append(eventType.getName());

            String methodKey = methodKeyBuilder.toString();
            Class<?> methodClass = method.getDeclaringClass();
            Class<?> methodClassOld = subscriberClassByMethodKey.put(methodKey, methodClass);
            // methodClassOld和methodClass存在继承关系,换句话说之前存入的同名同参方法由父类继承而来,则当前的method也可以添加
            if (methodClassOld == null || methodClassOld.isAssignableFrom(methodClass)) {
                // Only add if not already found in a sub class
                return true;
            } else {
                // Revert the put, old class is further down the class hierarchy
                subscriberClassByMethodKey.put(methodKey, methodClassOld);
                return false;
            }
        }

    
        void moveToSuperclass() {
            //初始化时的参数,默认为false
            if (skipSuperClasses) {
                clazz = null;
            } else {
                //向上追溯父类直到系统类结束
                clazz = clazz.getSuperclass();
                String clazzName = clazz.getName();
                // Skip system classes, this degrades performance.
                // Also we might avoid some ClassNotFoundException (see FAQ for background).
   
                if (clazzName.startsWith("java.") || clazzName.startsWith("javax.") ||
                        clazzName.startsWith("android.") || clazzName.startsWith("androidx.")) {
                    clazz = null;
                }
            }
        }
}

通过注释1@findUsingInfo处的方法得到了一个FindState对象:

   SubscriberMethodFinder.java
   
   private FindState prepareFindState() {
        synchronized (FIND_STATE_POOL) {
            for (int i = 0; i < POOL_SIZE; i++) {
                FindState state = FIND_STATE_POOL[i];
                if (state != null) {
                    FIND_STATE_POOL[i] = null;
                    return state;
                }
            }
        }
        return new FindState();
    }

在SubscriberMethodFinder类中维护了一个FindState对象池,应该为了避免对象频繁的创建和销毁造成内存抖动。

注释2@findUsingInfo处对FindState对象进行初始化赋值:

void initForSubscriber(Class<?> subscriberClass) {
            this.subscriberClass = clazz = subscriberClass;
            skipSuperClasses = false;
            subscriberInfo = null;
}

继续往下看注释3@findUsingInfo

SubscriberMethodFinder.java

private SubscriberInfo getSubscriberInfo(FindState findState) {
         //有缓存数据的话直接返回
        if (findState.subscriberInfo != null && findState.subscriberInfo.getSuperSubscriberInfo() != null) {
            SubscriberInfo superclassInfo = findState.subscriberInfo.getSuperSubscriberInfo();
            if (findState.clazz == superclassInfo.getSubscriberClass()) {
                return superclassInfo;
            }
        }

        // 而subscriberInfoIndexes则是在EventBus的构造方法中创建SubscriberMethodFinder对象时传入的,在此系列文章第二片中有提到,可知 subscriberInfoIndexes不为空
        if (subscriberInfoIndexes != null) {
            //这里的index对象对应的就是MyEventBusIndex类
            for (SubscriberInfoIndex index : subscriberInfoIndexes) {
                //将findState.clazz作为key,取出MyEventBusIndex中的map中存储的SubscriberInfo对象
                SubscriberInfo info = index.getSubscriberInfo(findState.clazz);
                if (info != null) {
                    return info;
                }
            }
        }
        return null;
    }

到此收集注册订阅方法的流程已结束,我们回过头来看一下EventBus.register()方法在注册完订阅方法之后还进行了什么操作:

EventBus.java

public void register(Object subscriber) {
        if (AndroidDependenciesDetector.isAndroidSDKAvailable() && !AndroidDependenciesDetector.areAndroidComponentsAvailable()) {
            // Crash if the user (developer) has not imported the Android compatibility library.
            throw new RuntimeException("It looks like you are using EventBus on Android, " +
                    "make sure to add the \"eventbus\" Android library to your dependencies.");
        }

        Class<?> subscriberClass = subscriber.getClass();
        List<SubscriberMethod> subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass);
        //当前已分析到这里
        synchronized (this) {
            for (SubscriberMethod subscriberMethod : subscriberMethods) {
                //遍历订阅方法,执行subscribe()方法
                subscribe(subscriber, subscriberMethod);
            }
        }
    }

继续往下看:

EventBus.java

private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) {
        Class<?> eventType = subscriberMethod.eventType;
        //将订阅者对象(如:MainActivity对象)与 订阅方法封装成一个新的数据结构
        Subscription newSubscription = new Subscription(subscriber, subscriberMethod);
        CopyOnWriteArrayList<Subscription> subscriptions = subscriptionsByEventType.get(eventType);
        if (subscriptions == null) {
            subscriptions = new CopyOnWriteArrayList<>();
            //建立eventType与subscriptions的对应关系
            subscriptionsByEventType.put(eventType, subscriptions);
        } else {
            if (subscriptions.contains(newSubscription)) {
                throw new EventBusException("Subscriber " + subscriber.getClass() + " already registered to event "
                        + eventType);
            }
        }

        //按优先级插入到list中,优先级高的在前面
        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);

        //如果当前方法订阅的是粘性事件
        if (subscriberMethod.sticky) {
            //默认为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>).
                //若stickyEvents中存储的未消费的Event事件(比如跳转MainActivity之前,
                //进行了postSticky()操作)与此方法接收的Event事件类型匹配,
                //则在此执行一次事件分发,也就是post操作,这也是粘性事件实现的核心原理。
                // 在此埋个坑,stickyEvents map集合中的数据是在什么时候填充的呢?
                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);
            }
        }
    }

到此register()的源码分析就结束了,下面来顺便看下unregister()的源码,有了register()的源码基础,大家也能猜个大概unregister()无非就是将订阅者(如:MainActivity对象)对应的map缓存中的数据移除调,我们来具体看下代码:

EventBus.java

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

正如我们的猜想,这部分比较简单,就不做过多分析了。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
EventBus是一种用于Android应用程序中发布/订阅事件的库。它遵循发布-订阅模式,允许不同组件之间进行松散耦合的通信。 在基于EventBus 3.0的APP开发中,你可以按照以下步骤进行: 1. 添加EventBus依赖 在项目的build.gradle文件中添加以下代码: ``` dependencies { implementation 'org.greenrobot:eventbus:3.2.0' } ``` 2. 创建事件类 创建一个事件类,它将包含你需要发送和接收的数据。例如: ``` public class MessageEvent { public final String message; public MessageEvent(String message) { this.message = message; } } ``` 3. 注册订阅者 在需要接收事件的组件中,注册订阅者。例如,在Activity中: ``` @Override public void onStart() { super.onStart(); EventBus.getDefault().register(this); } @Override public void onStop() { EventBus.getDefault().unregister(this); super.onStop(); } ``` 4. 发布事件 在需要发送事件的组件中,发布事件。例如,在Activity中: ``` EventBus.getDefault().post(new MessageEvent("Hello, world!")); ``` 5. 处理事件 在订阅者中,创建一个方法来处理接收到的事件。例如,在Activity中: ``` @Subscribe(threadMode = ThreadMode.MAIN) public void onMessageEvent(MessageEvent event) { // Do something with the event Toast.makeText(this, event.message, Toast.LENGTH_SHORT).show(); } ``` 以上就是基于EventBus 3.0的APP开发的基本步骤。通过使用EventBus,你可以轻松地在不同组件之间传递数据,从而实现应用程序中的松散耦合通信。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值