概述
EventBus是Android中的一个开源库,用来发布/订阅事件的总线。模型如下:
使用EventBus的优点
● 简化了组件间的通信
● 事件发送者和事件接收者间充分解耦
● 在Activities,Fragment,和后台线程中方便的执行
● 避免复杂和容易出错的依赖关系和生命周期问题
● 快速运行,特别是在优化的高性能设备上
● 轻量级(< 50k jar)
更多EventBus 特性的
基于API方便的注解:简单的将@Subscribe 声明在你的订阅者方法上。
Android 主线程分发:当与UI正在交互时,EventBus能够在主线程中直接分发事件,而不用去关注事件是如何被发送的。
后台线程的分发:如果你的订阅者正在处理一个长时间的运行任务,EventBus 同样能够使用后台线程分发事件来避免UI阻塞。
事件和订阅者的继承:在EventBus,面向对象的范例适用于事件和订阅类。
直接启动:你可以直接启动,不需要任何配置,在你的代码的任何地方使用默认的EventBus对象等等。
gitHub地址:https://github.com/greenrobot/EventBus/
四步开始应用EventBus
1.添加依赖
compile ‘org.greenrobot:eventbus:3.0.0’
2.定义事件
事件是普通的Java对象,没有特别的要求
public class MessageEvent {
public final String message;
public MessageEvent(String message) {
this.message = message;
}
}
3.准备订阅者
订阅者实现了事件处理方法(同样被称为“subscriber 方法”),当事件被post时,会被调用。它们使用@Subscribe注解定义。注意,EventBus 3 中的方法名称可以自由选择。
//这个方法将被调用,当一个消息事件被post后(在UI线程中)
@Subscribe(threadMode = ThreadMode.MAIN)
public void onMessageEvent(MessageEvent event) {
Toast.makeText(getActivity(), event.message, Toast.LENGTH_SHORT).show();
}
//这个方法将被调用,当一个SomeOtherEvent事件被post时。
@Subscribe
public void handleSomethingElse(SomeOtherEvent event) {
doSomethingWith(event);
}
订阅者也需要执行注册或者取消注册操作,只有订阅者被注册,它们将会收到事件,在Android中,activities和 fragments中,你应该通过它们的生命周期中注册:
@Override
public void onStart() {
super.onStart();
EventBus.getDefault().register(this);
}
@Override
public void onStop() {
EventBus.getDefault().unregister(this);
super.onStop();
}
4.post 事件
可以在代码的任何位置来post一个事件,所有的当前被注册的订阅者匹配事件类型将会接收它。
EventBus.getDefault().post(new MessageEvent(“Hello everyone!”));
粘性事件
在事件被post之后,一些事件会带有你感兴趣的信息。例如,一个初始化完成的信号事件。或者你有一些传感器或定位数据,你想要保存在最近的值中。你可以使用粘性事件,而不是实现你的缓存。EventBus在内存中保存了最近粘性事件的某些类型。粘性事件能够被分发到订阅者或显示查询。因此,你不需要任何多余的操作来处理已经可用的数据。
例如:
@Override
protected void onStart() {
super.onStart();
EventBus.getDefault().register(this);
}
@Override
protected void onStop() {
super.onStop();
EventBus.getDefault().unregister(this);
}
@OnClick(R.id.button)
public void onClick(View view){
EventBus.getDefault().postSticky(new MessageEvent("EventBus Test"));
}
@Subscribe(sticky = true, threadMode = ThreadMode.MAIN)
public void onEvent(MessageEvent event) {
tvText.setText(event.message);
}
上述代码在执行第一次之后,(back)退出,重新进入时,会直接调用onEvent方法。
简单讲,就是在发送事件之后再订阅该事件也能收到该事件,跟黏性广播类似。
手动获得和删除粘性事件
如上,当被注册时粘性事件会自动分发匹配订阅者,但有时它可能更方便手动检查粘性事件。同样它可能需要去remove 粘性事件,以便不再被分发。
例如:
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
}
removeStickyEvent方法被重载:当你执行这个类时,它将会返回之前的粘性事件。使用这个变量,我们可以改善上面的例子:
MessageEvent stickyEvent = EventBus.getDefault().removeStickyEvent(MessageEvent.class);
// Better check that an event was actually posted before
if(stickyEvent != null) {
// Now do something with it
}
分发线程(ThreadMode)
EventBus 能够为你处理线程,事件被post的线程能够与posting的线程不同。一个常见的用法是处理UI的改变。在Android中,UI改变必须在UI(main)线程中。另一方面,网络,或者耗时操作,必须没有运行在main 线程中。EventBus 帮助你处理这些工作,同步UI线程。
在EventBus中,你可以通过使用四个ThreadMode定义线程来调用事件处理方法。
ThreadMode: POSTING
默认的模式,订阅者将会被调用在与post 事件同一个线程中。事件传送同步完成,一旦post事件完成所有的订阅者将会被调用。这个ThreadMode意味着最少的开销,因为它避免了线程的切换。因此,当完成一个小的任务,不需要main 线程模式时,推荐模式。使用这个模式可以快速返回,避免线程阻塞。
@Subscribe(threadMode = ThreadMode.POSTING)
public void onMessage(MessageEvent event) {
log(event.message);
}
ThreadMode: MAIN
订阅者将会在Android主线程(UI线程)中被调用,如果在main 线程中post 事件,事件处理者将被直接调用,这时与ThreadMode: POSTING相同。
// Called in Android UI’s main thread
@Subscribe(threadMode = ThreadMode.MAIN)
public void onMessage(MessageEvent event) {
textField.setText(event.message);
}
ThreadMode: BACKGROUND
订阅者将在后台线程中被调用。如果post 线程是在子线程发出的,事件处理方法将被直接调用在post 线程中。如果post线程是UI线程发出的,EventBus 使用一个单一的后台线程将会按顺序传送它的所有的事件。
// Called in the background thread
@Subscribe(threadMode = ThreadMode.BACKGROUND)
public void onMessage(MessageEvent event){
saveToDisk(event.message);
}
ThreadMode: ASYNC
事件处理方法在一个独立的线程中调用,它是独立于post 线程和main 线程。使用这个模式,post 事件从不等待事件处理方法。事件处理方法应该使用这个模式,如果它们执行一些耗时操作,如网络访问。避免在同一时间触发大量的长时间运行的异步处理程序方法来限制并发线程的数量。Eventbus使用线程池来有效地重用线程完成的异步事件处理程序的通知。
// Called in a separate thread
@Subscribe(threadMode = ThreadMode.ASYNC)
public void onMessage(MessageEvent event){
backend.send(event.message);
}
优先级和事件取消
你可以在注册过程中为订阅方提供优先级,更改事件传递的顺序。高优先级的订阅者比低优先级的订阅者先接收到事件。默认优先级为0。你可以取消事件传递通过调用订阅者事件处理的cancelEventDelivery方法,任何其他的事件传递将会被取消。
@Subscribe(priority = 1);
public void onEvent(MessageEvent event) {
…
}
// Called in the same thread (default)
@Subscribe
public void onEvent(MessageEvent event){
// Process the event
…
EventBus.getDefault().cancelEventDelivery(event) ;
}
事件通常被高优先级订阅者取消,运行在ThreadMode.PostThread模式中,取消是受限制的。