什么是EventBus
先来一段官方介绍和配图
EventBus is a publish/subscribe event bus optimized for Android.
就是说EventBus是一个针对Android优化的发布/订阅事件总线。它可以做到:
- 简化组件之间的通信
- 简化代码结构
- ……
试想这样一个场景,一个Activity有两个fragment分别是f1, f2。有一个需求就是f1中的一个按钮被点击后改变f2的内容。有两个方法可以完成:
- 很暴力的方法,在f1中得到Activity的引用,然后通过Activity的到f2的引用从而调用f2的方法。
- f1定义一个接口,让Activity实现,从而让Activity调用f2的方法。
第一个方法将f1和Activity完全耦合起来,f1失去了独立性和复用性。推荐第二个方法,让f1和Activity解耦。
EventBus可以在开销小、代码优雅的同时解耦事件发布者和订阅者。
基本使用
注册
在Activity或者Fragment的onCreate()方法中注册EventBus
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
EventBus.getDefault().register(this);
}
在onDestroy()方法中取消注册
@Override
public void onDestroy() {
super.onDestroy();
EventBus.getDefault().unregister(this);
}
发布事件
通过post发布一个事件,传递一个我们自己定义的类
public class SampleEvent {
private String info;
public DelayEvent(String info) {
this.info = info;
}
public String getInfo() {
return info;
}
}
EventBus.getDefault().post(new SampleEvent(Item.items));
这样就完成了事件发布
订阅事件
订阅事件也就是处理事件,我们需要自己写一个处理事件的方法,参数必须是该事件的类型。
@Subscribe(threadMode = ThreadMode.MAIN)
public void handleSampleEvent(SampleEvent event) {
Log.d(TAG, event.getInfo());
}
该方法必须有一个Subscribe注解表示这是一个订阅事件的方法,threadMode指的是该方法在那个线程调用,有如下四种:
- Thread.POSTING:在发送事件的线程调用,默认就是这个。
- ThreadMode: MAIN:在主线程执行。
- ThreadMode: BACKGROUND:如果发布线程是主线程,那就创建新线程执行,否则直接在发布线程执行。
- ThreadMode: ASYNC:开启新线程,不依赖主线程和发布线程,这样发布方就不需要等待事件处理结束(若是在发布线程执行,肯定会阻塞该线程的),适用于耗时的任务。
总流程
看了上面的过程有可能会疑惑事件是怎么发布出去的,又是怎么得到的。其实在注册的时候EventBus就会通过反射得到该类下有@Subscribe的注解方法,然后保存起来,包括参数。然后在事件发布的时候去查询是否有参数匹配的(如这里的SampleEvent),匹配到了就调用,一个事件可以很多订阅者。
StickyEvent
SticykEvent叫做粘性事件,普通的事件在发布的时候马上查询是否有匹配,执行所有匹配后就删除该事件。而StickyEvent在EventBus里每一个类对应只有一个,也就是说会覆盖,假设多次发送粘性事件SampleEvent,最新的总是覆盖以前的,而且会被缓存下来不会删除。对应的订阅者也不一定要在发布之前订阅,因为粘性事件会被缓存,所以在发布后订阅也是一样的。
EventBus.getDefault().postSticky(new SampleEvent("1"));
EventBus.getDefault().postSticky(new SampleEvent("2"));
startActivity(new Intent(getActivity(), SecondActivity.class));
// SecondActivity.java
@Subscribe(threadMode = ThreadMode.MAIN, sticky = true)
public void onDelayEvent(DelayEvent event) {
Toast.makeText(SecondActivity.this, "dalay event:" + event.getInfo(), Toast.LENGTH_SHORT).show();
}
通过postSticky()发布,订阅需要注解sticky = true。
因为接受的粘性事件,所以这里订阅是在发布之后也可以收到,收到的只有一个,也就是第二个发出的SampleEvent
ventBus.getDefault().postSticky(new SampleEvent("2"));