一、EventBus的介绍
EventBus是事件总线的意思,是一个事件发布和订阅框架,解耦发布者和订阅者,用来简化Android的组件间通信,如Activity,Service,Fragment之间的通信等,在异步线程和主线程通信时也可以用到这个框架。
Android实现消息传递的方法有很多,比如Handler,全局广播,本地广播,Intent,接口回调,观察者模式等。他们有着不同的使用场景,handler实现线程间通信,比如子线程通知主线程改变ui;全局广播可以实现进程间通信,接收系统广播,或者在组件间通信;intent主要是在组件间通信传递一些简单的数据。
当一个事件在应用内传递,如果使用广播又觉得臃肿,如果使用接口回调需要多次回调,代码繁琐,那么可以使用EventBus,直接从发送事件的地方传递到接收事件的地方。
二、EventBus的使用
GitHub地址为https://github.com/greenrobot/EventBus
官方文档为http://greenrobot.org/eventbus/documentation/
1.添加依赖
implementation 'org.greenrobot:eventbus:3.1.1'
2.定义事件
定义一个类,即为一个事件,可以在事件中生命要传递的数据
public static class MessageEvent {
/* Additional fields if needed */
}
3.注册和反注册
在activity中在相应的生命周期,onCreate()或onStart()注册,在onDestory()或onPause()中反注册。
@Override
public void onStart() {
super.onStart();
EventBus.getDefault().register(this);
}
@Override
public void onStop() {
super.onStop();
EventBus.getDefault().unregister(this);
}
4.订阅事件
声明订阅事件的方法必须是public的,参数为想要订阅的事件。需要用注解@Subscribe来标识一个订阅方法,可以声明订阅方法在哪个线程执行,默认为POSTING
@Subscribe(threadMode = ThreadMode.MAIN)
public void onMessageEvent(MessageEvent event) {
/* Do something */
};
- POSTING:默认,表示事件处理函数的线程跟发布事件的线程在同一个线程
- MAIN:表示事件处理函数的线程在主线程(UI)线程
- BACKGROUND:表示事件处理函数的线程在后台线程
- ASYNC:表示无论事件发布的线程是哪一个,事件处理函数始终会新建一个子线程运行
5.发布事件
EventBus.getDefault().post(new MessageEvent());
6.事件优先级
同一个线程模型下,可以通过注解配置优先级设置调用的先后顺序,默认为0,数值越大执行优先级越高
@Subscribe(threadMode = ThreadMode.POSTING, priority = 0)
@Subscribe(threadMode = ThreadMode.POSTING, priority = 1)
7.粘性事件
事件可以在没有订阅方法时先发出来,等注册了订阅方法后,事件会被马上调用
EventBus.getDefault().postSticky(new MessageEvent());
@Subscribe(threadMode = ThreadMode.POSTING, sticky = true, priority = 1)
三、EventBus3.0索引加速
在3.0以前都是通过反射来获取订阅方法,通过对比方法名onEvent
开头的方法会被认为是订阅方法。
3.0之后引入了注解来标识订阅方法,在注册时通过反射注解来解析订阅方法,但是这种方法会比对比方法名耗时,所以引入了订阅索引(Subscriber Index),可以在编译时生成代码,准备好订阅方法的数据,就不需要反射了,性能大幅提高。官方文档http://greenrobot.org/eventbus/documentation/subscriber-index/
首先在Gradle构建脚本中添加依赖,并配置编译时参数
android {
defaultConfig {
javaCompileOptions {
annotationProcessorOptions {
//指定生成的文件为MyEventBusIndex
arguments = [ eventBusIndex : 'com.example.myapp.MyEventBusIndex' ]
}
}
}
}
dependencies {
implementation 'org.greenrobot:eventbus:3.1.1'
annotationProcessor 'org.greenrobot:eventbus-annotation-processor:3.1.1'
}
接下来编译运行,就会生成索引文件,注意 在gradle的版本5以上不会生成,需要修改到4.6。或者使用kapt,同时这样能在kotlin中使用。
写2个订阅方法
@Subscribe(priority = 1)
public void SUU(MyEvent w){
}
@Subscribe(priority = 2)
public void SUU1(MyEvent w){
}
build之后生成的代码,在\app\build\generated\source\kapt\debug\com\example\myapp\MyEventBusIndex.java
中
/** 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>();
//创建和保存一个订阅者信息SimpleSubscriberInfo,到集合中
putIndex(new SimpleSubscriberInfo(com.example.myapp.MainActivity.class, true,
new SubscriberMethodInfo[] {
//2个订阅方法对应的SubscriberMethodInfo对象
new SubscriberMethodInfo("SUU", com.example.myapp.MyEvent.class, ThreadMode.POSTING, 1,
false),
new SubscriberMethodInfo("SUU1", com.example.myapp.MyEvent.class, ThreadMode.POSTING, 2,
false),
}));
}
//保存一个订阅者信息到索引中
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;
}
}
}
使用索引
//使用索引创建EventBus单例
EventBus.builder().addIndex(new MyEventBusIndex()).installDefaultEventBus();
// Now the default instance uses the given index. Use it like this:
EventBus eventBus = EventBus.getDefault();