1:什么是EventBus?我们先来看看官方的定义:EventBus是Android和Java的发布/订阅事件总线。
官方的定义已经介绍得非常清楚了,EventBus就是基于观察者模式实现事件或数据的传递,用于简化程序组件通讯、线程通讯等。既然是基于观察者模式,那么肯定有观察者和被观察者了,观察者就是接受事件数据的方法,这个方法可以在任意页面任意线程。比如我下面准备举的列子是:要从ActivityOne传递数据到ActivityTwo中,那么我们的观察者方法就是在ActivityTwo的,首先在gradle降EventBus添加到项目中:
compile 'org.greenrobot:eventbus:3.1.1'
如果需要添加最新版本,可到GitHub查看,后面给出地址。
然后添加观察者的代码,观察方法如下:
// 该方法在消息发布时调用
@Subscribe(threadMode = ThreadMode.MAIN)
public void onMessageEvent(MessageEvent event) {
Toast.makeText(getActivity(), event.message, Toast.LENGTH_SHORT).show();
}
Subscribe是EventBus3之后引入的annotation,只要加了这个注解,编译的时候,就会生成相应的代码调用这个方法,(threadMode = ThreadMode.MAIN)指定观察者的线程,这里指定了UI线程。上面还有一个类MessageEvent,使用时需要自己定义,定义方式如下:
public class MessageEvent {
//这里定义了一个字符串,说明我们事件只传递一个字符串消息,<br/>
//也可以定义其它类型的对象,如:List对象
public final String message;
public MessageEvent(String message) {
this.message = message;
}
}
这里没什么需要说明的,还有我们需要在ActivityTwo中注册事件,一般建议在onStart方法注册,然后在Onstop方法中释放,代码如下:
@Override
public void onStart() {
super.onStart();
EventBus.getDefault().register(this);//注册
}
@Override
public void onStop() {
EventBus.getDefault().unregister(this);//取消注册
super.onStop();
}
最后看看发布事件的代码:
EventBus.getDefault().post(new MessageEvent("Hello everyone!"));//MessageEvent
MessageEvent就是我们前面定义的MessageEvent,给他的构造方法传入相应的数据即可。
到这里EventBus基本使用,就写完了,接下来看看一下线程配置。
刚才在定义onMessageEvent这个方法的时候,有一句@Subscribe(threadMode = ThreadMode.MAIN),@Subscribe是注解生成对象回调,这个不用解释了,然后说一下括号里面的(threadMode = ThreadMode.MAIN)这里指定了onMessageEvent运行在什么线程,因为事件不一定是在主线程发布,所以这个就是线程间通信了,我刚才指定的是主线程,不管事件在什么线程发布,这个方法都会在主线程运行。还有几个线程的配置如下
ThreadMode.POSTING:这个代表在什么线程发布事件,这个观察者方法就在哪个线程运行。
ThreadMode.BACKGROUND:如果调用post方法的线程不是主线程,则直接在该线程执行,如果是主线程,则切换到后台单例线程,多个方法公用同个后台线程,按顺序执行,避免耗时操作。
ThreadMode.ASYNC开辟新独立线程,用来执行耗时操作,例如网络访问
EventBus内部使用了线程池,但是要尽量避免大量长时间运行的异步线程,限制并发线程数量,可以通过EventBusBuilder修改,默认使用Executors.newCachedThreadPool(),后面探讨这个配置。到这里基本使用写完了,后面是一些比较少用的配置,如果有兴趣可以继续往下读。
Configuration(配置)
EventBus Builder类配置EventBus的各个方面。例如,这里是如何构建一个EventBus,它在没有订阅者的情况下保存安静,不发送消息。
EventBus eventBus = EventBus.builder()
.logNoSubscriberMessages(false)
.sendNoSubscriberEvent(false)
.build();
还有一个是当订阅者发生异常的时候,可以会发送一个可以不处理的异常。
EventBus eventBus = EventBus.builder().throwSubscriberException(true).build();
EventBusBuilder 还可以通过里面的installDefaultEventBus()这个方法配置默认实列。使用代码如下:
EventBus.builder().throwSubscriberException(BuildConfig.DEBUG).installDefaultEventBus();
这里配置的是:当我们在开发的时候,抛异常就会发生崩溃;但是正是发布的版本,抛出这个异常不做处理。
注意:这里必须在第一次调用getDefault()之前配置,而且只能配置一次,所以建议在Application里面使用。
还有一个比较实用的Sticky Events,先描述一下场景,拿刚才那个列子来说:如果ActivityTwo还没有注册的时候,ActivityOne的事件已经触发了,那么用刚才的方法,再打开ActivityTwo,是收不到消息的,EventBus有其它方法解决这个问题,先看看发送事件的方法:
EventBus.getDefault().postSticky(new MessageEvent("Hello everyone!"));
这里只是把post换成了postSticky方法,这个方法可以将最新的消息保存起来,然后打开ActivityTwo的时候,再传给监听器。那么相应ActivityTwo的注解也要改成如下:
//这里选择了在UI线程回调
@Subscribe(sticky = true, threadMode = ThreadMode.MAIN)
public void onMessageEvent(MessageEvent event){
Log.i("MyActivity" , event.message);
textview.setText(event.message);
}
@Override
public void onStart() {
super.onStart();
EventBus.getDefault().register(this);
}
@Override
public void onStop() {
EventBus.getDefault().unregister(this);
super.onStop();
}
这样就可以做到保存最新的消息,等注册了,再发送。
然后EventBus还提供了事件优先级别的设置,使用方式如下:
@Subscribe(priority = 1);
public void onMessageEvent(MessageEvent event) {
Log.i("MyActivity" , event.message);
}
priority的值越大,级别越高,注意:线程不影响优先级。
当同一条信息,被多个Activity监听的时候,如果我们只想让一个Activity收到消息就不让其它Activity收到,可以使用如下方法取消:
@Subscribe
public void onMessageEvent(MessageEvent event) {
//防止发送给其它订阅者
EventBus.getDefault().cancelEventDelivery(event) ;
}
然后看看添加Kotlin的支持
apply plugin: 'kotlin-kapt' // ensure kapt plugin is applied
dependencies {
compile 'org.greenrobot:eventbus:3.1.1'
kapt 'org.greenrobot:eventbus-annotation-processor:3.1.1'
}
kapt {
arguments {
arg('eventBusIndex', 'com.example.myapp.MyEventBusIndex')
}
}
混淆规则
-keepattributes *Annotation*
-keepclassmembers class ** {
@org.greenrobot.eventbus.Subscribe <methods>;
}
-keep enum org.greenrobot.eventbus.ThreadMode { *; }
# Only required if you use AsyncExecutor
-keepclassmembers class * extends org.greenrobot.eventbus.util.ThrowableFailureEvent {
<init>(java.lang.Throwable);
}
EventBus还有很多有趣的api,比如index索引加速,后面继续探讨。
官网:http://greenrobot.org/eventbus/