美文网首页
EventBus3.0源码解析

EventBus3.0源码解析

作者: 噜噜丶 | 来源:发表于2018-03-23 13:43 被阅读0次

EventBus的注册

EventBus.getDefault().register(this);

那么我们来看一下EventBus.getDefault(),到底做了一下什么操作

/** Convenience singleton for apps using a process-wide EventBus instance. */
    public static EventBus getDefault() {
        if (defaultInstance == null) {
            synchronized (EventBus.class) {
                if (defaultInstance == null) {
                    defaultInstance = new EventBus();
                }
            }
        }
        return defaultInstance;
    }

就是拿到了EventBus的实例,而且使用了双重效验的单例模式
然后我们再来看.register(),这个顾名思义叫做注册,我们从源码来进行分析

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(subscriberClass);通过名字不难看出是找到订阅者的函数并且保存在List中,那么我们来看看这个函数

List<SubscriberMethod> findSubscriberMethods(Class<?> subscriberClass) {
        //先从缓存CACHE的list去取订阅者
        List<SubscriberMethod> subscriberMethods = METHOD_CACHE.get(subscriberClass);
        if (subscriberMethods != null) {
            return subscriberMethods;
        }

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

这里做的操作先从缓存订阅者的List去取,如果有就直接返回,如果没有继续,来到if,ignoreGeneratedIndex这个参数,需要通过EventBus的构造去找,默认为false,找到这个订阅者的Method后再次存入缓存的List中,那么我们来到findUsingInfo;

private List<SubscriberMethod> findUsingInfo(Class<?> subscriberClass) {
        FindState findState = prepareFindState();
        findState.initForSubscriber(subscriberClass);
        while (findState.clazz != null) {
 //  这个地方第一次进来getSubscriberInfo会返回null,所以会走到findUsingReflectionInSingleClass
            findState.subscriberInfo = getSubscriberInfo(findState);
            if (findState.subscriberInfo != null) {
                SubscriberMethod[] array = findState.subscriberInfo.getSubscriberMethods();
                for (SubscriberMethod subscriberMethod : array) {
                    if (findState.checkAdd(subscriberMethod.method, subscriberMethod.eventType)) {
                        findState.subscriberMethods.add(subscriberMethod);
                    }
                }
            } else {
                findUsingReflectionInSingleClass(findState);
            }
            findState.moveToSuperclass();
        }
        return getMethodsAndRelease(findState);
    }

通过prepareFindState构造了一个FindState,主要用来保存订阅者的class等等,我们也来瞅一下源码

static class FindState {
        final List<SubscriberMethod> subscriberMethods = new ArrayList<>();
        final Map<Class, Object> anyMethodByEventType = new HashMap<>();
        final Map<String, Class> subscriberClassByMethodKey = new HashMap<>();
        final StringBuilder methodKeyBuilder = new StringBuilder(128);

        Class<?> subscriberClass;
        Class<?> clazz;
        boolean skipSuperClasses;
        SubscriberInfo subscriberInfo;

        void initForSubscriber(Class<?> subscriberClass) {
            this.subscriberClass = clazz = subscriberClass;
            skipSuperClasses = false;
            subscriberInfo = null;
        }
    ................省略
}
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;
            }
        }
        if (subscriberInfoIndexes != null) {
            for (SubscriberInfoIndex index : subscriberInfoIndexes) {
                SubscriberInfo info = index.getSubscriberInfo(findState.clazz);
                if (info != null) {
                    return info;
                }
            }
        }
        return null;
    }

这里贴了俩个方法,都是上面调用的,一个是FindState,保存了订阅者的Class,一个
通过FindState找到SubscriberInfo,不过这里要注意,一开始的话这个SubscriberInfo会返回null
也就是来到了findUsingReflectionInSingleClass这个方法。

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

在这个方法里使用了大量的反射,对订阅者的class进行扫描Annotation获得订阅者的函数,并对其进行保存。

相关文章

  • 自己实现简单的EventBus功能

    1、下面是EventBus3.0的一些用法和源码分析 EventBus使用详解 EventBus源码解析 2、接...

  • EventBus3.0 性能提升之添加索引

    EventBus3.0 源码解析 一文中,在分析Subscriber的register()过程中,说到过一个方法方...

  • EventBus3.0 源码解析

    EventBus,是一个基于Publish/Subscribe的事件总线框架。更通俗的讲,EventBus就是一个...

  • Eventbus3.0源码解析

    根据官方demo 首先你需要先在activity中注册 register 所以我们先从getDefault方法开始...

  • EventBus3.0源码解析

    EventBus的注册 那么我们来看一下EventBus.getDefault(),到底做了一下什么操作 就是拿到...

  • EventBus3.0源码解析

    前言 EventBus是一个优秀的事件订阅/发布框架,充分解耦了事件的发布者和订阅者,简化了代码。 记得刚来公司...

  • EventBus3.0源码解析

    看了好几次EventBus源码了,这次总算基本上搞清楚了,简单来说就是调用 EventBus.getDefault...

  • EventBus3.0 源码解析

    简介 我们知道,Android应用主要是由4大组件构成。当我们进行组件间通讯时,由于位于不同的组件,通信方式相对麻...

  • EventBus3.0源码解析

    EventBus是一个Android事件发布/订阅框架,通过解耦发布者和订阅者简化 Android 事件传递。Ev...

  • 解析EventBus3.0源码

    EventBus 介绍 EventBus是Android和Java的一个发布和订阅事件总线第三方库。 官网 Fea...

网友评论

      本文标题:EventBus3.0源码解析

      本文链接:https://www.haomeiwen.com/subject/mlfxcftx.html