EventBus 是一款针对Android优化的发布/订阅(publish/subscribe)事件总线。主要功能是替代Intent,Handler,Broadcast在Fragment,Activity,Service,线程之间传递消息。简化了应用程序内各组件,组件与后台线程间的通信。优点代码简洁,以及将发送者和订阅者解耦。
使用步骤
compile 'org.greenrobot:eventbus:3.0.0'
这里的事件是一个任意的POJO 没有任何要求
public class MessageEvent {
public final String message;
public MessageEvent(String message) {
this.message = message;
}
}
准备订阅者
使用注解 @Subscribe ,在3.0中对方法名称没有任何要求 当发送事件时EventBus会调用方法
// This method will be called when a MessageEvent is posted (in the UI thread for Toast)
@Subscribe(threadMode = ThreadMode.MAIN)
public void onMessageEvent(MessageEvent event) {
Toast.makeText(getActivity(), event.message, Toast.LENGTH_SHORT).show();
}
// This method will be called when a SomeOtherEvent is posted
@Subscribe
public void handleSomethingElse(SomeOtherEvent event) {
doSomethingWith(event);
}
注册/取消订阅
@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!"));
官网指南 http://greenrobot.org/eventbus/documentation/how-to-get-started/
EventBus 通过 threadMode 决定订阅事件 在哪个线程处理,threadMode的取值 有四个枚举类型
POSTING。 默认值,将会与发送线程一致,发送事件在哪个线程,订阅者就在哪个线程处理
// Called in the same thread (default)
// ThreadMode is optional here
@Subscribe(threadMode = ThreadMode.POSTING)
public void onMessage(MessageEvent event) {
log(event.message);
}
MAIN 。 UI线程,订阅者将会在UI线程处理
// Called in Android UI's main thread
@Subscribe(threadMode = ThreadMode.MAIN)
public void onMessage(MessageEvent event) {
textField.setText(event.message);
}
BACKGROUND 。 后台线程处理,如果发送者在UI线程发出就会另开线程处理,否则就直接在同一线程处理,不会在UI线程处理就对了
// Called in the background thread
@Subscribe(threadMode = ThreadMode.BACKGROUND)
public void onMessage(MessageEvent event){
saveToDisk(event.message);
}
ASYNC 。异步,订阅者将会另开一个线程处理,无论发送者从哪个线程发出
// Called in a separate thread
@Subscribe(threadMode = ThreadMode.ASYNC)
public void onMessage(MessageEvent event){
backend.send(event.message);
}
官网指南 http://greenrobot.org/eventbus/documentation/delivery-threads-threadmode/
优先级
EventBus 通过 priority
属性决定优先级 ,默认0 值越高 优先级越高。
@Subscribe(priority = 1);
public void onEvent(MessageEvent event) {
...
}
事件取消
EventBus 通过 cancelEventDelivery(Object event)
取消事件,这可是优先级高的特权了。
// Called in the same thread (default)
@Subscribe
public void onEvent(MessageEvent event){
// Process the event
...
// Prevent delivery to other subscribers
EventBus.getDefault().cancelEventDelivery(event) ;
}
官网指南 http://greenrobot.org/eventbus/documentation/priorities-and-event-cancellation/
一般我们使用 EventBus.getDefault()
得到EventBus实例,
如果有别的需求可以使用 EventBusBuilder 类构建EventBus,例如 关闭log
EventBus eventBus = EventBus.builder()
.logNoSubscriberMessages(false)
.sendNoSubscriberEvent(false)
.build();
或者说 当订阅者抛出异常时 发送 SubscriberExceptionEvent
事件
EventBus eventBus = EventBus.builder().throwSubscriberException(true).build();
默认情况下 订阅者抛出异常EventBus会捕获异常并发一个 SubscriberExceptionEvent
事件
我们可以通过 installDefaultEventBus()
方法我们的配置放到默认实例上;但是要在使用 EventBus.getDefault()
之前
EventBus.builder().throwSubscriberException(BuildConfig.DEBUG).installDefaultEventBus();
官网指南 http://greenrobot.org/eventbus/documentation/configuration/
对于一般的事件,我们首先要注册订阅者,然后发送事件,订阅者才能收到事件。如果先发送事件,再订阅此事件,将收不到事件,而粘性事件恰恰相反,粘性事件是可以先发送,然后再注册订阅者,后注册的订阅者依然可以接收到事件(ps:在发送前注册的也可以收到)
先发送粘性事件
EventBus.getDefault().postSticky(new MessageEvent("Hello everyone!"));
再启动一个Activity 仍然可以接受到之前发送的事件
属性 sticky 的取值决定是否是粘性事件
ps:你不注册的话,啥事件也是收不到的
@Override
public void onStart() {
super.onStart();
EventBus.getDefault().register(this);
}
// UI updates must run on MainThread
@Subscribe(sticky = true, threadMode = ThreadMode.MAIN)
public void onEvent(MessageEvent event) {
textField.setText(event.message);
}
@Override
public void onStop() {
EventBus.getDefault().unregister(this);
super.onStop();
}
移除粘性事件
如果你不移除粘性事件,那么它将一直存在,直到你程序被杀死
MessageEvent stickyEvent = EventBus.getDefault().getStickyEvent(MessageEvent.class);
// Better check that an event was actually posted before
if(stickyEvent != null) {
// "Consume" the sticky event
EventBus.getDefault().removeStickyEvent(stickyEvent);
// Now do something with it
}
官网传送门 http://greenrobot.org/eventbus/documentation/configuration/sticky-events/
订阅索引是3.0中的新特性,是可选项。
在3.0中由于使用了注解,比起使用反射来遍历方法的2.4版本逊色不少。但开启索引后性能远远超出旧版本。 看作者放出的图
既然使用索引后那么叼,那就看看怎么使用索引
注意项
使用 apt插件的方式
buildscript {
dependencies {
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
}
}
apply plugin: 'com.android.application'
apply plugin: 'com.neenbedankt.android-apt'
dependencies {
compile 'org.greenrobot:eventbus:3.0.0'
apt 'org.greenrobot:eventbus-annotation-processor:3.0.1'
}
apt {
arguments {
eventBusIndex "com.example.myapp.MyEventBusIndex"
}
}
使用索引
编译过后 会生成 MyEventBusIndex类,没有生成就多编译几遍
EventBus eventBus = EventBus.builder().addIndex(new MyEventBusIndex()).build();
将索引配置到默认实例中
EventBus.builder().addIndex(new MyEventBusIndex()).installDefaultEventBus();
// Now the default instance uses the given index. Use it like this:
EventBus eventBus = EventBus.getDefault();
还可以添加多个不同的library中索引
EventBus eventBus = EventBus.builder()
.addIndex(new MyEventBusAppIndex())
.addIndex(new MyEventBusLibIndex()).build();
官网指南 http://greenrobot.org/eventbus/documentation/subscriber-index/
-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);
}
官网指南 http://greenrobot.org/eventbus/documentation/proguard/
懒得翻译了,直接看吧 http://greenrobot.org/eventbus/documentation/asyncexecutor/
感谢各位大神的分享
Demo地址: https://github.com/sky-mxc/AndroidDemo/tree/master/event