Subscriber Index(订阅者索引)是一个可选择的优化技术,用来加速初始化subscriber注册。
利用反射来读取订阅类中的订阅方法信息
通过使用EventBus annotation processor(EventBus注解处理器),订阅者索引在编译期间就会被创建。虽然没有规定必须使用它,但是由于它在Android中最佳性能,官方推荐使用此方式。
使用索引的先决条件
注意只有用@Subscriber注解的方法才能被编入索引到,同时subscriber类和事件类必须是public。并且,由于Java注解处理本身的技术限制,@Subscribe 注解不能使用在匿名类中。
当EventBus不能使用索引,它将自动恢复到在运行时通过反射的方式,因此它也能正常工作,只是变得更慢了。
怎么生成索引?
使用注解处理器
如果你不是使用 Android Gradle Plugin version 2.2.0 或更高版本,请以android-apt方式来配置。
启用索引生成功能,你需要使用annotationProcessor 属性把EventBus注解处理器添加到你的build。另外,设置一个eventBusIndex参数去指定你想要产生索引类的全路径类名。比如说,添加下面的部分到你的Gradle build 脚本。
android {
defaultConfig {
javaCompileOptions {
annotationProcessorOptions {
arguments = [ eventBusIndex : 'com.example.myapp.MyEventBusIndex' ]
}
}
}
}
dependencies {
compile 'org.greenrobot:eventbus:3.0.0'
annotationProcessor 'org.greenrobot:eventbus-annotation-processor:3.0.1'
}
我自己试过不行,不知道为什么?
使用android-apt
打开App的build.gradle,在dependencies中添加最新的EventBus依赖:
compile 'org.greenrobot:eventbus:3.0.0'
在项目gradle的dependencies中引入apt编译插件:
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
然后在App的build.gradle中应用apt插件,并设置apt生成的索引的包名和类名:
apply plugin: 'com.neenbedankt.android-apt'
apt {
arguments {
eventBusIndex "com.study.sangerzhong.studyapp.MyEventBusIndex"
}
}
接着在App的dependencies中引入EventBusAnnotationProcessor:
apt 'org.greenrobot:eventbus-annotation-processor:3.0.1'
在Rebuild Project操作前,确保有@Subscribe注解的方法,否则不会生成索引类。 Rebuild Project后,就会发现在\ProjectName\app\build\generated\source\apt\PakageName\ 下看到通过注解处理器生成的索引类,这样我们便可以在初始化EventBus时应用我们生成的索引了。
在这里会生成类名为MyEventBusIndex的索引类:
/** This class is generated by EventBus, do not edit. */
public class MyEventBusIndex implements SubscriberInfoIndex {
private static final Map<Class<?>, SubscriberInfo> SUBSCRIBER_INDEX;
static {
SUBSCRIBER_INDEX = new HashMap<Class<?>, SubscriberInfo>();
putIndex(new SimpleSubscriberInfo(MainActivity.class, true, new SubscriberMethodInfo[] {
new SubscriberMethodInfo("onEventA", PayEvent.class, ThreadMode.ASYNC),
}));
putIndex(new SimpleSubscriberInfo(MyIntentService.class, true, new SubscriberMethodInfo[] {
new SubscriberMethodInfo("onEventBB", PayEvent.class),
}));
}
private static void putIndex(SubscriberInfo info) {
SUBSCRIBER_INDEX.put(info.getSubscriberClass(), info);
}
@Override
public SubscriberInfo getSubscriberInfo(Class<?> subscriberClass) {
SubscriberInfo info = SUBSCRIBER_INDEX.get(subscriberClass);
if (info != null) {
return info;
} else {
return null;
}
}
}
可以看出是使用一个静态HashMap来保存订阅类的相关信息,其中包括了订阅类的class对象,是否需要检查父类,以及所有事件响应函数的信息。
怎么把索引类应用到Android?
当你实例化EventBus时,通过以下方式:
EventBus eventBus = EventBus.builder().addIndex(new MyEventBusIndex()).build();
或者,你想要在整个app中使用设置了索引类的EventBus实例作为默认单例。
EventBus.builder().addIndex(new MyEventBusIndex()).installDefaultEventBus();
// Now the default instance uses the given index. Use it like this:
EventBus eventBus = EventBus.getDefault();
对比通过编译时反射方式
在3.0版本中,EventBus提供了一个EventBusAnnotationProcessor注解处理器来在编译期通过读取@Subscribe注解,并解析和处理其中所包含的信息,然后生成java类来保存订阅者中所有的事件响应函数,这样就比在运行时使用反射来获得订阅者中所有事件响应函数的速度要快。
参考
http://greenrobot.org/eventbus/documentation/subscriber-index/