因为EventBus 3.0 和之前的版本差异较大,下面介绍的内容是基于EventBus3.0 。EventBus,是一个基于Publish/Subscribe的事件总线框架, 这里不做过多详细介绍。
下面是EventBus工程和文档地址:
GitHub : github.com/greenrobot/…
官方文档:greenrobot.org/eventbus/do…
配置
这里介绍一下配置。
-
基本配置: 在app 工程下的
build.gradle
中添加依赖:dependencies { ...... // 省略部分依赖 implementation 'org.greenrobot:eventbus:3.1.1' }
-
如果使用索引(index)在app 工程下的
build.gradle
中添加依赖:android { defaultConfig { .... // javaCompileOptions { annotationProcessorOptions { arguments = [ eventBusIndex : 'com.cfox.eventbusdemo.index.EventBusIndex' ] } } } } dependencies { implementation 'org.greenrobot:eventbus:3.1.1' annotationProcessor 'org.greenrobot:eventbus-annotation-processor:3.1.1' }
快速使用
-
创建消息类
这个类可以任意定义, 作为传输使用public class MessageObjectOne { private String info; public String getInfo() { return info; } public void setInfo(String info) { this.info = info; } }
-
注册
注册使用EventBus实例register(Object subscriber)
方法进行注册。@Override protected void onStart() { super.onStart(); EventBus.getDefault().register(this); }
-
注销
注销使用EventBus实例unregister(Object subscriber)
方法进行注册。@Override protected void onStop() { super.onStop(); EventBus.getDefault().unregister(this); }
-
订阅接事件 订阅接收方法使用注解
@Subscribe
@Subscribe(threadMode = ThreadMode.MAIN, priority = 2, sticky = true) public void subMessageOne(MessageObjectOne msgOne) { Log.d(TAG, "subMessageOne: " + msgOne.getInfo()); }
上面代码发现,注解
@Subscribe
有三个参数,还有不同的值。下面会介绍 -
发布消息
MessageObjectOne object = new MessageObjectOne(); object.setInfo("hello world"); EventBus.getDefault().post(object);
@Subscribe参数
threadMode
ThreadMode.POSTING(默认):如果使用事件处理函数指定了线程模型为POSTING,那么该事件在哪个线程发布出来的,事件处理函数就会在这个线程中运行,也就是说发布事件和接收事件在同一个线程。在线程模型为POSTING的事件处理函数中尽量避免执行耗时操作,因为它会阻塞事件的传递,甚至有可能会引起ANR.
ThreadMode.MAIN: 事件的处理会在UI线程中执行。事件处理时间不能太长,长了会ANR的。
ThreadMode.BACKGROUND:如果事件是在UI线程中发布出来的,那么该事件处理函数就会在新的线程中运行,如果事件本来就是子线程中发布出来的,那么该事件处理函数直接在发布事件的线程中执行。在此事件处理函数中禁止进行UI更新操作。
ThreadMode.ASYNC:无论事件在哪个线程发布,该事件处理函数都会在新建的子线程中执行,同样,此事件处理函数中禁止进行UI更新操作。
priority
订阅方法的优先级影响订阅方法的执行顺序。优先级越高越被先执行。
sticky
如果设置为true
则该订阅事件为粘性事件(后面会详细介绍)。
使用索引(index)
在EventBus中使用索引可以提升app效率。使用索引的配置上面已经介绍了,下面介绍一下:
arguments = [ eventBusIndex : 'com.cfox.eventbusdemo.index.EventBusIndex' ]
上面这句是配置生成索引的目录(com.cfox.eventbusdemo.index
)和索引类的类名(EventBusIndex
), 配置好索引后,重新build
一下工程就会生成索引类。
索引为什么能提高app的效率,如果没有使用索引,在注册的时候会通过反射获取类中订阅的事件,使用索引后注册时在索引中查询订阅事件,所以效率会提高很多。
-
添加使用索引
配置好索引后,还要将生成的索引添加的项目中,否则索引是不会生效的。索引建议在应用的Application
中添加,如下:public class App extends Application { @Override public void onCreate() { super.onCreate(); EventBus.builder().addIndex(new EventBusIndex()).installDefaultEventBus(); } }
如果在项目中使用EventBus.getDefault()
方法使用EventBus,在使用索引的时候一定要使用installDefaultEventBus()
方法添加索引。
有的文章中使用build()
方法添加索引,如下方法:
public class App extends Application {
private EventBus mEventBus;
@Override
public void onCreate() {
super.onCreate();
mEventBus = EventBus.builder().addIndex(new EventBusIndex()).build();
}
public EventBus getEventBus() {
return mEventBus;
}
}
注意:如果使用这种方式添加索引一定要使用build()
返回的EventBus实例, 如果使用EventBus.getDefault()
方法使用EventBus,索引将不会生效。
stick 事件
-
stick 事件?
stick 事件就是如果某个对象的stick 事件被发布后,该对象的stick订阅事件没有注册到EvnetBus上,当该对象的stick订阅事件注册到EventBus上时, 该对象的订阅事件将立即被执行。 -
如何订阅stick 事件
在订阅事件时将sticky
设置为true
(sticky = true
)@Subscribe(threadMode = ThreadMode.MAIN, sticky = true) public void subMessageOne(MessageObjectOne msgOne) { Log.d(TAG, "subMessageOne: " + msgOne.getInfo()); }
-
发布stick 事件
MessageObjectOne object = new MessageObjectOne(); object.setInfo("hello world"); EventBus.getDefault().postSticky(object);
深入一点
上面介绍了比较简单的是使用,EventBus 使用是比较灵活的,下面以使用节点进一步讲解。
-
注册
官方文档中的示例如下:@Override public void onStart() { super.onStart(); EventBus.getDefault().register(this); } @Override public void onStop() { EventBus.getDefault().unregister(this); super.onStop(); }
重官方给出的示例中是在
onStart
和onStop
中进行注册和注销, 其实这只是其中的一个使用场景, 不必纠结在什么地方注册和注销,了解原理根据需求灵活使用。注册的是什么?
从注册方式中可以看到register
方法中传入的是一个对象。通过查看源码知道,注册时通过反射获取到订阅的事件(如果使用索引,从索引类中获取),也就是说,任何对象只要对象中订阅了事件,就会把订阅的事件注册到EventBus中。如下示例:将一个普通对象注册到EventBus 中
public class EventHandler { private static final String TAG = "EventHandler"; @Subscribe public void text(MessageObject object) { Log.d(TAG, "text: " + object.getInfo()); } } EventHandler mHandler = new EventHandler(); EventBus.getDefault().register(mHandler); // 注册 EventBus.getDefault().unregister(mHandler); // 注销
注册后,如果发布这个类型的消息,这个类中订阅的事件就会响应。不用的时候注销一下就可以了。
-
订阅事件
在EventBus3.0中订阅事件使用注解@Subscribe
,所以可以随意命名。事件参数必须只有一个参数。不同消息的订阅
EventBus是根据事件消息参数的类型进行分发相响应的,也就是说,post一种类型的消息,只有订阅相同消息的订阅事件才能响应。如下订阅事件代码示例:@Subscribe(threadMode = ThreadMode.MAIN) public void subMessageOne(MessageObjectOne msgOne) { Log.d(TAG, "subMessageOne: " + msgOne.getInfo()); } @Subscribe(threadMode = ThreadMode.MAIN) public void subMessageTwo(MessageObjectTwo msgTwo) { Log.d(TAG, "subMessageTwo: " + msgTwo.getInfo()); }
使用下面方式发送消息将只有
subMessageOne
订阅事件得到响应MessageObjectOne object = new MessageObjectOne(); object.setInfo("hello world"); EventBus.getDefault().post(object);