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

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

    //公有构造
    public EventBus()
    //私有构造
    EventBus(EventBusBuilder builder)

如果我们直接调用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;
    }

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

    public static EventBusBuilder builder() {
        return new EventBusBuilder();
    }

然后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)

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

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

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

   EventBus.builder()
            .eventInheritance(false)
            .logNoSubscriberMessages(true)
            .strictMethodVerification(true)
            .sendSubscriberExceptionEvent(true)
            .installDefaultEventBus()

好了,看了源码之后,还发现可以通过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)
    }

这样也可以,哈哈。 好了,这里大概把初始化的源码讲完了,比较简单,其实就是配置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. AndroidDependenciesDetector.isAndroidSDKAvailable()
 Android平台是否可用主要是通过反射framework.jar包中的Looper.java类,如果在运行环境能反射该类,
 并且invoke getMainLooper()方法可以取得Looper对象且不为空,则表示当前运行在Android环境中。
  1. 查找模块中的消费函数信息
    主要通过如下代码获取
   List<SubscriberMethod> subscriberMethods = 
   subscriberMethodFinder.findSubscriberMethods(subscriberClass);

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

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

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

 SubscriberMethodFinder(List<SubscriberInfoIndex> subscriberInfoIndexes, boolean 
 strictMethodVerification, boolean ignoreGeneratedIndex) {
        this.subscriberInfoIndexes = subscriberInfoIndexes;
        this.strictMethodVerification = strictMethodVerification;
        this.ignoreGeneratedIndex = ignoreGeneratedIndex;
}

构造的几个参数都是从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;
        }
    }

先看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);
    }

在分析里面的函数之前,需要先搞清楚一下这个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;
                }
            }
        }
    }

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

好了,最后还剩下一个查找消费函数的方法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");
            }
        }
    }

上述分析了在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);
    }

我们在初始化中的使用了函数索引的方式去定义消费函数,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;
    }

紧接着又调用了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;
    }

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

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

    public void register(Object subscriber) {
   		...
   		...
        synchronized (this) {
            for (SubscriberMethod subscriberMethod : subscriberMethods) {
                subscribe(subscriber, subscriberMethod);
            }
        }
    }

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

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值