想全面了解EventBus的童鞋可以参考这里:https://blog.youkuaiyun.com/wangchao1412/article/details/84629815
Subscriber Index(订阅者索引)是一个可选择的优化技术,用来加速初始化subscriber注册。
通过使用EventBus annotation processor(EventBus注解处理器),订阅者索引在编译期间就会被创建。虽然没有规定必须使用它,但是由于它在Android中最佳性能,官方推荐使用此方式。
如何使用Subscriber Index
添加依赖:
implementation 'org.greenrobot:eventbus:3.0.0' //有了它就可以在编译时找subscribermethod了 annotationProcessor 'org.greenrobot:eventbus-annotation-processor:3.0.1'
在android中添加: defaultConfig { javaCompileOptions { annotationProcessorOptions { //编译时会生成新文件,com.example.myapp表示路径,MyEventBusIndex类名 arguments = [ eventBusIndex : 'com.example.myapp.MyEventBusIndex' ] } } } 新文件会生成在build\generated\source\apt\debug下。
注册EventBus
//把生成的MyEventBusIndex注入EventBus中
EventBus.builder().addIndex(new MyEventBusIndex()).build().regist();
或者
EventBus.builder().addIndex(new MyEventBusIndex()).installDefaultEventBus().register(this);
下面来从源码角度看一下EventBus是如何实现编译时注解的
AbstractProcessor的类
EventBus的编译时做的操作是在EventBusAnnotationProcessor中进行的,来看一下
@SupportedAnnotationTypes("org.greenrobot.eventbus.Subscribe")指明对@Subscribe进行筛选,会执行到process中,在这里进行操作生成什么样的文件。
@SupportedOptions(value = {"eventBusIndex", "verbose"})指明option的name,可以根据processingEnv.getOptions().get(key)去获取相应的值,这里eventBusIndex指的是我们生成文件的位置,这个我们需要在app的gradle中去自己设置。
下面是process方法,主要做的就是查找subscriberMethod和把信息按格式写入到java文件。
process中的collectSubscribers
在这里遍历Annotation,获取他的element,因为@subscribe是作用在Method上的,所以可以直接转成把element转成method,然后再checkHasNoErrors中进行筛除(如下)。在添加到methodsByClass中。
如果找到有符合的订阅者的话,就写入到java文件中。
createInfoIndexFile
右图是生成的文件格式,可以对照着右图解析左图的代码。
主要有导包的操作,还有固定的类的写法和方法的写法。需要动态写的是右图putIndex的写法,这里我们看一下是怎样写的。
writeIndexLines
writeCreateSubscriberMethods
这样我们就在指定的路径下生成了这个文件。
这里在静态代码块中直接调用了putIndex把SubscriberInfo添加到了map集合中。还提供了getSubScriberInfo去获取subscribe对应的subscriberInfo。
这里先看在putIndex的时候new 了一个SimpleSubScriberInfo,看一下
SimpleSubscriberInfo
这里呢把SubscriberMethodInfo[] methodInfos(装着订阅方法的信息)提供给自己,然后条用
super(subscriberClass, null, shouldCheckSuperclass);然后在getSubscriberMethods方法中去调用父类createSubscriberMethod
把SubscriberMethodInfo转成了SubscriberMethod。下面我们来看一下父类 AbstractSubscriberInfo。
AbstractSubscriberInfo
它实现的接口
可以看到,AbstractSubscriberInfo实现了接口中的getSubscriberClass方法和getSuperSubscriberInfo方法,而
getSubscriberMethods是在SimpleSubscriberInfo中实现的。
捋一下:在生成的文件MyEventBusIndex中getSubscriberInfo去获取SimpleSubscriberInfo,在这里是从map中取值,把SimpleSubscriberInfo转成了它的父类实现的接口SubscriberInfo,在SimpleSubscriberInfo中实现了getSubscriberMethods,在SimpleSubscriberInfo的父类AbstractSubscriberInfo中实现了getSubscriberClass和getSuperSubscriberInfo。所以直接拿到SubscriberInfo进行统一化管理取值更加方便。
SubscriberInfo
下面就看一下EventBus中是怎么对SubscribeInfo进行运用的。
点进去看一下
再点进去
这里的subscriberInfoIndexes怎么来的?最上边提到过使用编译器注解需要将文件通过建造者传入EventBus中。
上变看到我们在外部通过addIndex加入Builder中,他又把加入的subscriberInfoIndex添加到了subscriberInfoIndexes集合中
,又在EventBus构造中把subscriberInfoIndexes传给了SubscriberMethodFinder,所以我们这里的subscriberInfoIndexes是就有值了。
这里的subscriberInfoIndexes就是我们最上边提到的,也就是我们编译器生成的java文件传入到了eventBus中。
在贴一遍getSubscriberInfo中的方法。
通过index.getSubscriberInfo()就回去到SubscriberInfo了。并返回赋值给findState.subscriberInfo
然后直接从subscriberInfo.getSubscriberMethods获取到SubscriberMethod[]。接下来的就和上篇讲到的流程贯穿了。
就说到这里!!!!