• Android应用内组件通讯之EventBus源码分析之初始化与订阅(二)


    上一篇文章水了一篇消息总线通信库EventBus的API使用,这一次来梳理一下它的源码,EventBus的源码不多,我们依旧按照API的使用方式来分析源代码会更好理解一点

    为了方便起见,这里我把EventBus的注册传入对象类称之为订阅模块,把事件回调函数称之为消费函数

    初始化

    首先,EventBus的对象获取时通过EventBus.getDefault()来获取的,当看到这样的API调用的时候,我们自然而然的就能想到这是用的单例模式,让我们看看源码

    //定义一个全局的静态变量defaultInstance,并使用volatile关键字修饰
    //保证线程读取安全
    static volatile EventBus defaultInstance;
    /** Convenience singleton for apps using a process-wide EventBus instance. */
    //使用多重同步校验获取EventBus对象
    public static EventBus getDefault() {
            EventBus instance = defaultInstance;
            if (instance == null) {
                synchronized (EventBus.class) {
                    instance = EventBus.defaultInstance;
                    if (instance == null) {
                        instance = EventBus.defaultInstance = new EventBus();
                    }
                }
            }
            return instance;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    getDefault()函数挺简单,就是静态变量defaultInstance不为空的情况下,直接返回EventBus对象,如果为空的情况下,则取new了一个EventBus对象,EventBus类一共有两个构造函数,分别是:

        //公有构造
        public EventBus()
        //私有构造
        EventBus(EventBusBuilder builder)
    
    • 1
    • 2
    • 3
    • 4

    如果我们直接调用getDefault()函数,创建EventBus对象,则内部是调用公有构造,公有构造函数中,使用类中定义的静态私有常量DEFAULT_BUIDLER传给私有构造函数初始化EventBus,代码如下:

    private static final EventBusBuilder DEFAULT_BUILDER = new EventBusBuilder();
     
    public EventBus() {
        this(DEFAULT_BUILDER);
    }
    
    EventBus(EventBusBuilder builder) {
            logger = builder.getLogger();
            subscriptionsByEventType = new HashMap<>();
            typesBySubscriber = new HashMap<>();
            //粘性事件集
            stickyEvents = new ConcurrentHashMap<>();
            mainThreadSupport = builder.getMainThreadSupport();
            //主UI线程消息提交器
            mainThreadPoster = mainThreadSupport != null ? mainThreadSupport.createPoster(this) : null;
            //后台线程提交器
            backgroundPoster = new BackgroundPoster(this);
            //异步线程提交器
            asyncPoster = new AsyncPoster(this);
            //消费函数定义总数
            indexCount = builder.subscriberInfoIndexes != null ? builder.subscriberInfoIndexes.size() : 0;
            //订阅模块管理
            subscriberMethodFinder = new SubscriberMethodFinder(builder.subscriberInfoIndexes,
                    builder.strictMethodVerification, builder.ignoreGeneratedIndex);
            logSubscriberExceptions = builder.logSubscriberExceptions;
            logNoSubscriberMessages = builder.logNoSubscriberMessages;
            
            sendSubscriberExceptionEvent = builder.sendSubscriberExceptionEvent;
            sendNoSubscriberEvent = builder.sendNoSubscriberEvent;
            //当事件触发时,如果方法调用异常,是否直接抛出异常,默认false
            throwSubscriberException = builder.throwSubscriberException;
            //继承事件,为true的情况下,当订阅者订阅事件的父类类型时,能
            //得监听到该父类事件的所有子类事件, 默认true
            eventInheritance = builder.eventInheritance;
            //线程池
            executorService = builder.executorService;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37

    从上面基本上就可以看到,EventBus的初始化采用了构造者模式来初始化EventBus的工作环境,默认情况下采用DEFAULT_BUILDER构建信息,当然我们也可以自己来定制相关参数,那么久需要在调用getDefault()函数之前先来配置自己的参数,EventBus同样提供了一个builder()方法来获取EventBusBuidler对象

        public static EventBusBuilder builder() {
            return new EventBusBuilder();
        }
    
    • 1
    • 2
    • 3

    然后EventBusBuilder中提供了如下函数来让我们定制工作环境

     //配置为true后,消息分发过程中如果出现异常,将异常打印到logcat中
     - logSubscriberExceptions(boolean logSubscriberExceptions)
     //配置为true后,如果事件没有订阅模块,则打印LOG
     - logNoSubscriberMessages(boolean logNoSubscriberMessages)
     //配置为true后,如分发过程中出现异常情况,则将Exception作为异常事件分发
     - sendSubscriberExceptionEvent(boolean sendSubscriberExceptionEvent) 
     //分发没有订阅模块的事件
     - sendNoSubscriberEvent(boolean sendNoSubscriberEvent)
     //抛出分发过程中出现的异常
     - throwSubscriberException(boolean throwSubscriberException)
     //继承事件,模块监听事件的父类事件类型,则该事件的所有子类事件都能被该模块接收
     - eventInheritance(boolean eventInheritance)
     //线程池配置
     - executorService(ExecutorService executorService)
     //没有使用到
     - skipMethodVerificationFor(Class<?> clazz)
     //强制使用反射获取事件回调函数,即使其通过方法索引配置的。
     - ignoreGeneratedIndex(boolean ignoreGeneratedIndex)
     //消费函数严格校验,主要是事件回调函数如果不是public的,则抛出异常
     - strictMethodVerification(boolean strictMethodVerification) 
     //添加消费函数回调索引
     - addIndex(SubscriberInfoIndex index) 
     //日志器
     - logger(Logger logger)
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    通过上述定制自己的EventBus工作环境之后,调用如下两个方法来初始化EventBus

    //这是用来将参数赋予给默认的总线类,并创建EventBus对象
    public EventBus installDefaultEventBus() 
    //这是根据当前配置创建一个新的EventBus对象
    public EventBus build()
    
    • 1
    • 2
    • 3
    • 4

    好了,源码分析到这里,我们大概应该对EventBus的实例构建有个粗略的了解了,原来我们在上一篇中,直接调用了getDefault()函数创建的EventBus只是使用了默认的构造器,那我们如果要定制默认Eventbus对象的运行环境,还可以在EventBus.getDefault()调用前做来配置:

       EventBus.builder()
                .eventInheritance(false)
                .logNoSubscriberMessages(true)
                .strictMethodVerification(true)
                .sendSubscriberExceptionEvent(true)
                .installDefaultEventBus()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    好了,看了源码之后,还发现可以通过index的方式来注册事件回调方法

       class RegisterSubscriber : SubscriberInfoIndex {
            private val SUBSCRIBER_INDEX: HashMap<Class<*>, SubscriberInfo> = HashMap()
            init {
                val registerMethodInfo = arrayOf(
                    SubscriberMethodInfo("indexCallback", SubEvent::class.java, ThreadMode.MAIN),
                    SubscriberMethodInfo("indexCallback", SubEvent1::class.java, ThreadMode.BACKGROUND)
                )
                val registerMethodInfo1 = arrayOf(
                    SubscriberMethodInfo("callback", SubEvent::class.java, ThreadMode.MAIN)
                )
                SUBSCRIBER_INDEX[MainActivity::class.java] = SimpleSubscriberInfo(MainActivity::class.java, false, registerMethodInfo)
                SUBSCRIBER_INDEX[DemoService::class.java] = SimpleSubscriberInfo(DemoService::class.java, false, registerMethodInfo1)
            }
    
            override fun getSubscriberInfo(subscriberClass: Class<*>): SubscriberInfo? {
                return SUBSCRIBER_INDEX[subscriberClass]
            }
        }
        
     EventBus.builder()
                .eventInheritance(false)
                .logNoSubscriberMessages(true)
                .strictMethodVerification(true)
                .sendSubscriberExceptionEvent(true)
                .ignoreGeneratedIndex(false)
                .addIndex(RegisterSubscriber())
                .installDefaultEventBus()
    
    class MainActivity : AppCompatActivity(){
    	 override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)
            EventBus.getDefault().register(this)
         }
           fun indexCallback(event:SubEvent){
            Log.i("xx_debug","indexCallback SubEvent: $event")
        }
    
        fun indexCallback(event:SubEvent1){
            Log.i("xx_debug","indexCallback SubEvent1: $event")
        }
    
        override fun onDestroy() {
            super.onDestroy()
            EventBus.getDefault().unregister(this)
        }
    }
    
    class DemoService : Service() {
        override fun onCreate() {
            super.onCreate()
            EventBus.getDefault().register(this)
        }
    
        fun callback(e: SubEvent){
            Log.i("xx_debug", "service callback: $e")
        }
    
        override fun onDestroy() {
            super.onDestroy()
            EventBus.getDefault().unregister(this)
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62

    这样也可以,哈哈。 好了,这里大概把初始化的源码讲完了,比较简单,其实就是配置Builder构造器的参数。接下来看注册流程。

    注册

    事件监听模块通过 EventBus.getDefault().register(Object subscriber) 方法来完成,贴一下源码:

        public void register(Object subscriber) {
            //首先判断是否为Android平台,如果是Android平台,但是安卓组件不可用,则抛出异常
            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.");
            }
    		//通过传入的Object实例获取Class类
            Class<?> subscriberClass = subscriber.getClass();
            //根据订阅模块的Class类型,获取该模块的消费函数信息(一个订阅模块可以有多个消费函数,所以这里用List集合来存储消费函数信息)
            List<SubscriberMethod> subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass);
            synchronized (this) {
            	//开始订阅
                for (SubscriberMethod subscriberMethod : subscriberMethods) {
                    subscribe(subscriber, subscriberMethod);
                }
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    一步一步分析:

    1. AndroidDependenciesDetector.isAndroidSDKAvailable()
     Android平台是否可用主要是通过反射framework.jar包中的Looper.java类,如果在运行环境能反射该类,
     并且invoke getMainLooper()方法可以取得Looper对象且不为空,则表示当前运行在Android环境中。
    
    • 1
    • 2
    1. 查找模块中的消费函数信息
      主要通过如下代码获取
       List<SubscriberMethod> subscriberMethods = 
       subscriberMethodFinder.findSubscriberMethods(subscriberClass);
    
    • 1
    • 2

    上面在初始化章节的时候看到过subscriberMethodFinder的赋值,

     subscriberMethodFinder = new SubscriberMethodFinder(builder.subscriberInfoIndexes,
                    builder.strictMethodVerification, builder.ignoreGeneratedIndex);
    
    • 1
    • 2

    看到这个类的名称就知道它是干啥的了,所以编码的过程中,清晰的命名还是很重要的,这个类就是用来查找订阅模块中的消费函数的。它的构造函数如下

     SubscriberMethodFinder(List<SubscriberInfoIndex> subscriberInfoIndexes, boolean 
     strictMethodVerification, boolean ignoreGeneratedIndex) {
            this.subscriberInfoIndexes = subscriberInfoIndexes;
            this.strictMethodVerification = strictMethodVerification;
            this.ignoreGeneratedIndex = ignoreGeneratedIndex;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    构造的几个参数都是从EventBuilder里面拿出来赋值给它的,几个参数的意义之前已经说过了,这个 SubscribeInfoIndexes的子集就是上面那个Demo中,通过函数索引的方式来定义消费函数监听事件的RegisterSubscriber这个类。继续往下走:

    List<SubscriberMethod> findSubscriberMethods(Class<?> subscriberClass) {
           //首先看缓存中有没有这个订阅模块信息,有的话直接返回,节省时间
            List<SubscriberMethod> subscriberMethods = METHOD_CACHE.get(subscriberClass);
            if (subscriberMethods != null) {
                return subscriberMethods;
            }
    
    		//没有缓存则继续找,如果不通过函数索引配置的方式,则通过注解从class信息中查找消费函数
            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;
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    先看ignoreGeneratedIndex = true的情况吧,也就是通过注解标记事件处理函数的方式。

        private List<SubscriberMethod> findUsingReflection(Class<?> subscriberClass) {
        	//从对象池中获取FindState对象
            FindState findState = prepareFindState();
            findState.initForSubscriber(subscriberClass);
            //往上递归查找查找事件,遇到基类(以java,javax,android,androidx包名开头的类)则停止搜索
            while (findState.clazz != null) {
            	//查找消费函数定义信息,并保存到findState中的subscriberMethods集合中
                findUsingReflectionInSingleClass(findState);
                //移到subscriberClass的父类Class继续扫描,直到遇到原生API定义的类则停止
                findState.moveToSuperclass();
            }
      		//返回消费函数信息
            return getMethodsAndRelease(findState);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    在分析里面的函数之前,需要先搞清楚一下这个FindState是什么东东,FindState类定义在SubscriberMethodFinder类中,是一个静态类,仅用于SubscriberMethodFinder内,工具人无疑。看看它的定义吧,内容还比较多

     static class FindState {
            final List<SubscriberMethod> subscriberMethods = new ArrayList<>();
            //(event class : Method) 某个订阅模块中的事件类型对应的消费函数Method类
            final Map<Class, Object> anyMethodByEventType = new HashMap<>();
            //(method key : Class) 消费函数签名与对应的订阅模块Class类的对应关系
            final Map<String, Class> subscriberClassByMethodKey = new HashMap<>();
            final StringBuilder methodKeyBuilder = new StringBuilder(128);
    		//订阅模块的Class类
            Class<?> subscriberClass;
            Class<?> clazz;
            boolean skipSuperClasses;
            SubscriberInfo subscriberInfo;
    
    		//初始化订阅器信息
            void initForSubscriber(Class<?> subscriberClass) {
                this.subscriberClass = clazz = subscriberClass;
                skipSuperClasses = false;
                subscriberInfo = null;
            }
    
    		//释放资源
            void recycle() {
                subscriberMethods.clear();
                anyMethodByEventType.clear();
                subscriberClassByMethodKey.clear();
                methodKeyBuilder.setLength(0);
                subscriberClass = null;
                clazz = null;
                skipSuperClasses = false;
                subscriberInfo = null;
            }
    
            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.
                //检测当前事件类型是否有对应的消费函数,如果没有,则直接添加,然后返回成功
                Object existing = anyMethodByEventType.put(eventType, method);
                if (existing == null) {
                    return true;
                } else {
                	//如果当前事件类型之前已经有与之对应的Method的了,则继续检查value对象是否为
                	//Method类型,为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);
                }
            }
    		
    		//检查函数签名
            private boolean checkAddWithMethodSignature(Method method, Class<?> eventType) {
                methodKeyBuilder.setLength(0);
                methodKeyBuilder.append(method.getName());
                methodKeyBuilder.append('>').append(eventType.getName());
    			//methodKey格式, exp: eventCallback>String
                String methodKey = methodKeyBuilder.toString();
                //获取定义该Method的Class类
                Class<?> methodClass = method.getDeclaringClass();
                //根据函数签名获取定义该函数的class类,如果子类未定义,则返回添加成功,
                //如果子类中已经定义过并且已经缓存的methodClassOld是methodClass的子类,则校验成功
                //否则返回失败。
                Class<?> methodClassOld = subscriberClassByMethodKey.put(methodKey, methodClass);
                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;
                }
            }
    
    		//支持父类查找的情况下,调用此方法,则将需要遍历的Class类重置为clazz的父类
            void moveToSuperclass() {
                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
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93

    FindState分析完了,其实它就是一个在register过程中的工具类,用来缓存订阅模块中的消费函数相关信息,因为我们的订阅模块可能存在各种继承关系。对着findUsingReflection这个函数中的逻辑看就很清晰了,先以当前register传入的对象为基点向上遍历扫描所有父类中可能存在的消费函数,每个Class分析完成之后通过FindState的moveToSuperclass方法继续往上扫描,直到遇到java或者android的原生api类为止。所以当我们在使用EventBus过程中,如下定义都是可行的

    open class RootClass{
        @Subscribe
        fun rootConsumer(value:String){
            Log.i("xx_debug","root consume the $value")
        }
    }
    
    open class ParentClass : RootClass(){
        @Subscribe
        fun parentConsumer(value:String){
            Log.i("xx_debug","parent consume the $value")
        }
    }
    
    class ChildClass : ParentClass(){
        init {
            EventBus.getDefault().register(this)
        }
    
        @Subscribe
        fun eventConsumer(value:String){
            Log.i("xx_debug","child consume the $value")
        }
    }
    
    //触发时,上述中的所有Consumer都会被调用打印
    EventBus.getDefault().post("111")
    
    2022-08-03 17:12:01.792 8346-8346/com.test.kotlintest I/xx_debug: child consume the 111
    2022-08-03 17:12:01.792 8346-8346/com.test.kotlintest I/xx_debug: parent consume the 111
    2022-08-03 17:12:01.792 8346-8346/com.test.kotlintest I/xx_debug: root consume the 111
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    好了,最后还剩下一个查找消费函数的方法findUsingRelectionInSingleClass方法

    private void findUsingReflectionInSingleClass(FindState findState) {
            Method[] methods;
            try {
                // This is faster than getMethods, especially when subscribers are fat classes like Activities
               //查找订阅类中的所有定义的函数,结合上面的分析,我们知道了这个clazz是一直在变的,while
               //循环一次clazz就赋值给了当前Class的父类Class,直到遇到原生API停止。
                methods = findState.clazz.getDeclaredMethods();
            } catch (Throwable th) {
                // Workaround for java.lang.NoClassDefFoundError, see https://github.com/greenrobot/EventBus/issues/149
                try {
                    methods = findState.clazz.getMethods();
                } catch (LinkageError error) { // super class of NoClassDefFoundError to be a bit more broad...
                    String msg = "Could not inspect methods of " + findState.clazz.getName();
                    if (ignoreGeneratedIndex) {
                        msg += ". Please consider using EventBus annotation processor to avoid reflection.";
                    } else {
                        msg += ". Please make this class visible to EventBus annotation processor to avoid reflection.";
                    }
                    throw new EventBusException(msg, error);
                }
                findState.skipSuperClasses = true;
            }
            //获取到Class中定义的所有方法后,通过注解标记,遍历出定义的消费函数
            for (Method method : methods) {
                int modifiers = method.getModifiers();
                //事件触发函数的访问域必须是public,且非抽象方法,静态方法
                if ((modifiers & Modifier.PUBLIC) != 0 && (modifiers & MODIFIERS_IGNORE) == 0) {
                    //获取函数中的入参类型
                    Class<?>[] parameterTypes = method.getParameterTypes();
                    //事件回调函数只允许存在一个入参定义
                    if (parameterTypes.length == 1) {
                        //查看该函数是否有@Subscribe注解修饰,如果存在,则为消费函数
                        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)) {
                	//如果消费函数不是public或者定义了其他的方法修饰符则报错
                    String methodName = method.getDeclaringClass().getName() + "." + method.getName();
                    throw new EventBusException(methodName +
                            " is a illegal @Subscribe method: must be public, non-static, and non-abstract");
                }
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56

    上述分析了在ignoreGeneratedIndex = true的情况下,查找消费函数信息的流程,那等于该值为false的情况呢,继续回到findSubscriberMethods函数中,走到了如下函数:

     private List<SubscriberMethod> findUsingInfo(Class<?> subscriberClass) {
            FindState findState = prepareFindState();
            findState.initForSubscriber(subscriberClass);
            while (findState.clazz != null) {
            	//前面都是一样,这里则是从构造器中传入的函数索引信息中取订阅信息,函数索引的值以及在Finder中的赋值在初始化中已经介绍过了,这里直接拿到用。
                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);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    我们在初始化中的使用了函数索引的方式去定义消费函数,Demo中自定义的RegisterSubscriber类里面的函数都是字符串,那这里是怎么一个转换方式呢? 在findUsingInfo函数的子流程getSubscriberInfo函数中可以得到结果

    private SubscriberInfo getSubscriberInfo(FindState findState) {
    		//findState.subscriberInfo.getSuperSubscriberInfo() 使用SimpleSubscriberInfo时为null
            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) {
                	//这里结合之前的Demo看,调用的是RegisterSubscriber中的getSubscriberInfo方法
                	//自己实现的,返回了类型为findState.clazz的SubscriberInfo
                	// return SUBSCRIBER_INDEX[subscriberClass]
                	//它的value是这种SimpleSubscriberInfo(MainActivity::class.java, false, registerMethodInfo)
                    SubscriberInfo info = index.getSubscriberInfo(findState.clazz);
                    if (info != null) {
                        return info;
                    }
                }
            }
            return null;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    紧接着又调用了SubscriberInfo的getSubscriberMethods方法

    @Override
    //定义在SimpleSubscriberInfo中
        public synchronized SubscriberMethod[] getSubscriberMethods() {
            int length = methodInfos.length;
            SubscriberMethod[] methods = new SubscriberMethod[length];
            for (int i = 0; i < length; i++) {
                SubscriberMethodInfo info = methodInfos[i];
                调用父类中的createSubscriberMethod方法构建了SubscriberMethodInfo对象
                methods[i] = createSubscriberMethod(info.methodName, info.eventType, info.threadMode,
                        info.priority, info.sticky);
            }
            return methods;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    createSubscriberMethod方法定义在抽象类AbstractSubscriberInfo中,可以根据函数名转成了Method对象

     protected SubscriberMethod createSubscriberMethod(String methodName, Class<?> eventType, ThreadMode threadMode,
                                                          int priority, boolean sticky) {
            try {
                Method method = subscriberClass.getDeclaredMethod(methodName, eventType);
                return new SubscriberMethod(method, eventType, threadMode, priority, sticky);
            } catch (NoSuchMethodException e) {
                throw new EventBusException("Could not find subscriber method in " + subscriberClass +
                        ". Maybe a missing ProGuard rule?", e);
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    后面的流程基本就跟注册一样了,遍历父类,查找类中的定义的消费函数信息。这里还没完,这里才把消费函数的搜集走完,接下来继续回到register函数中,开始注册:

        public void register(Object subscriber) {
       		...
       		...
            synchronized (this) {
                for (SubscriberMethod subscriberMethod : subscriberMethods) {
                    subscribe(subscriber, subscriberMethod);
                }
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    subscribe函数比较简单,就是构建一个Subscription对象,然后将其加入到subscriptionsByEventType的HashMap中,如果是粘性事件则触发一次post

     private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) {
            Class<?> eventType = subscriberMethod.eventType;
            //构建Subscription对象
            Subscription newSubscription = new Subscription(subscriber, subscriberMethod);
            //从本地缓存中查找当前事件的订阅模块集合,并将
            CopyOnWriteArrayList<Subscription> subscriptions = subscriptionsByEventType.get(eventType);
            if (subscriptions == null) {
                subscriptions = new CopyOnWriteArrayList<>();
                subscriptionsByEventType.put(eventType, subscriptions);
            } else {
            	//Subscription重写了equals,这里会对比subscriber是不是同一个对象,以及消费函数名称是否一致
            	//如果同一个订阅模块已经有相同事件类型的消费函数,则是重复订阅,报错。
                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;
                }
            }
    	
    		//将订阅模块中的所有订阅事件类型也接入Map中
            List<Class<?>> subscribedEvents = typesBySubscriber.get(subscriber);
            if (subscribedEvents == null) {
                subscribedEvents = new ArrayList<>();
                typesBySubscriber.put(subscriber, subscribedEvents);
            }
            subscribedEvents.add(eventType);
    
    		//最后如果是粘性事件,则触发一次post动作
            if (subscriberMethod.sticky) {
                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).
                    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);
                }
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56

    总结一下,EventBus的初始化通过构造者模式来完成,默认提供了一个构造器,也可以通过builder()的静态方法来自己构造EventBus运行环境,EventBus在注册时有两种方式去查找消费函数的Method对象,一个是通过@Subscribe注解,一个是通过在构造器中传入SubscriberInfoIndex实例来指定模块中的函数索引等信息,查找到消费函数信息之后,会构建一个Subscription的订阅器,EventBus中会通过事件类型分类保存这些订阅器对象,将订阅同一类型事件的订阅器保存在HashMap中,同时还会将每个订阅模块所订阅的事件类型保存在另外一个HashMap中,至于后面怎么用,下一篇再接着写吧。

  • 相关阅读:
    华为路由器忘记密码怎么恢复
    免费的电子书搜索引擎-FreeMbook
    蓝牙核心规范(V5.4)10.3-BLE 入门笔记之BIS篇
    WPF里ItemsControl的分组实现
    【Leetcode刷题】复制带随机指针的链表&&有效的括号
    WEB安全问题
    un7.29:Linux——centos中如何安装与配置redis?
    Docker镜像文件介绍启动tomcat
    羽夏 MakeFile 简明教程
    拼多多回应六万人砍价不成功:不实;苹果回应iOS 15.4正式版续航翻车;AMD FSR 2.0 即将面世|极客头条
  • 原文地址:https://blog.csdn.net/zjfengdou30/article/details/126089591