EventBus是一款针对Android优化的发布/订阅事件总线。主要功能是替代Intent、Handler、BroadCast在Fragment、Activity、Service、线程之间传递消息。优点是开销小,代码更优雅,以及将发送者和接收者解耦。
翻译过来其实也就这么核心几条:
1. 简化组件间的通信
(1).对发送和接受事件解耦
(2).可以在Activity,Fragment,和后台线程间执行
(3).避免了复杂的和容易出错的依赖和生命周期问题
2. 让你的代码更简洁
3. 更快
4. 更轻量(jar包小于50K)
5. 实践证明已经有一亿多的APP中集成了EventBus
6. 拥有先进的功能比如线程分发,用户优先级等等
有一种需求,是你将在Activity中获得网络请求拿到结果之后,再在这个Activity中将结果信息进行判断。所以说这个Activity能发送也能接收。
在这两个Activity中毋庸置疑一个Activity中有post方法负责发送事件, 另一个Activity中注册订阅者,来负责接收。很多初学的朋友肯定不少误认为这样就可以了,往往忽视了一个重要的问题,那就是Activity的生命周期影响了订阅者的注册,从而影响了事件的传送,可能会造成传送失败。
我们分析一下可能传送失败的原因。为什么取名叫“订阅者“,大家要知道EventBus是先订阅,然后再发送。”订阅在前,发送在后“ 。接收者先订阅,并且它的Activity必须还”活着“,这样以来不同的Activity之间才能顺利传Event。
举个例子, A的Activity 发送事件, B的Activity 接收 A发送的事件。B如果想接收A的事件,那就先打开B Activity,B中执行了订阅者的注册方法,B注册好了以后再跳转A Activity(此时B堆到栈里并未finish), A发送事件后,B成功接收事件。 如果在跳转A的时候顺便把B finish了, 也就说明B 的订阅者不存在了,那么A发送事件,再跳转B,B只是重新注册了一下订阅者,但接收不到的。
**总结一下**EventBus有一种情况是不可以使用的,那就是订阅者未先于发送者启动,或者先于发送者启动后被杀掉了,只要订阅者不存在,那么这事件就没法接收了。
so,且记口诀:先订阅者且活着,发送能成功。
那么先发送,后订阅就一点也不可以吗??
答案是可以的,如何做到先发送,后订阅还能 成功的传递事件呢??
有以下两种方式:
1.在 发送者的 onStop方法中 发送事件。
如果A是发送事件, B 是接收事件, 在A 中 打开B Activity 并且完成事件传递。
这种情况是先发送后注册订阅者,但是如果在发送者A的 onStop方法中发送,那么onStop方法是在 B Activity 打开之后才调用,所以说 那个时候B还活着了。
2.使用官方的Sticky Events
官方为了解决这种问题:EventBus还支持发送黏性事件。何为黏性事件呢?简单讲,就是在发送事件之后再订阅该事件也能收到该事件,跟黏性广播类似。
看看官网的描述
Some events carry information that is of interest after the event is posted. For example, an event signals that some initialization is complete. Or if you have some sensor or location data and you want to hold on the most recent values. Instead of implementing your own caching, you can use sticky events. EventBus keeps the last sticky event of a certain type in memory. The sticky event can be delivered to subscribers or queried explicitly. Thus, you don’t need any special logic to consider already available data.
直接翻译:
一些事件进行信息感兴趣的事件后发布。 例如,一个事件信号,一些初始化完成。 或者如果你有传感器位置数据和你想抓住最近的值。 而不是实现自己的缓存,您可以使用黏性的事件。 EventBus保持过去的事件的特定类型在内存中。 黏性的事件可以交付给用户或显式查询。 因此,你不需要任何特殊的逻辑来考虑可用的数据。
如何使用,以下的例子
public class BActivity extends Activity {
// 某个点击事件
@Override
public void onClick(View v) {
Event event= new Event(10);
// 发布Sticky事件
EventBus.getDefault().postSticky(event);
// 跳转到B页面
Intent intent = new Intent(this, AActivity.class);
startActivity(intent);
}
}
最后我们看看AActivity如何接收数据。
public class AActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_a);
// 以Sticky的形式注册
EventBus.getDefault().registerSticky(this);
}
@Subscriber
private void receiveUser(Event event){
// 这里实现你的逻辑即可, event即为传递过来的Event对象
}
}