EventBus是一个Android端优化的publish/subscribe消息总线,简化了应用程序内各组件间、组件与后台线程间的通信。比如请求网络,等网络返回时通过Handler或Broadcast通知UI,两个Fragment之间需要通过Listener通信,这些需求都可以通过EventBus实现。
首先你要为你的app添加依赖库:
implementation 'org.greenrobot:eventbus:3.1.1'
定义待发送实体类,类型可以是任意java bean
public class MsgEvent {
public final String username;
public final int age;
public MsgEvent(String username, int age) {
this.username = username;
this.age = age;
}
}
注册订阅者(也就是接收者),并在其生命周期绑定和解绑订阅者,大部分场景(activity和fragment)可以在onstart和onstop进行操作,其中的threadMode指定订阅的方法体运行在那种线程中
@Subscribe(threadMode = ThreadMode.MAIN)
public void onMessage(MessageEvent event) {
Log.i("test", event.username + event.age);
}
@Override
public void onStart() {
super.onStart();
EventBus.getDefault().register(this);
}
@Override
public void onStop() {
EventBus.getDefault().unregister(this);
super.onStop();
}
既然你在某个地方订阅了内容,当然就会在某个地方发布消息。举个例子,你的这个activity需要http请求,而http请求你肯定是在异步线程中操作,其返回结果后,你可以这么写:
EventBus.getDefault().post(new MsgEvent("嘉文四世", 1000));
假如在项目中,从activity A跳转到activity B,并发送了一个消息给activity B,发现activity B注册的订阅者无法收到消息。
原因:Eventbus普通的订阅事件,即eventbus.getDefault().post(xxx)方法必须是在订阅后发送消息才可接收到,从A启动B,此时A已发送,B还未注册,所以B无法收到A的事件。
解决办法:使用EventBus粘性事件,用它可以实现订阅在消息发送后注册接收收到消息
EventBus.getDefault().postSticky(new MessageEvent("张三", 34));
@Subscribe(threadMode = ThreadMode.MAIN, sticky = true)
public void onMessage(MessageEvent event) {
Log.i("test", event.username + event.age);
}
ThreadMode.POSTING
订阅者将在发布事件的同一线程中调用。这是默认值。事件传递是同步完成的,一旦发布完成,所有订阅者都将被调用。此ThreadMode意味着开销最小,因为它完全避免了线程切换。因此,这是已知完成的简单任务的推荐模式,是一个非常短的时间而不需要主线程。使用此模式的事件处理程序应该快速返回以避免阻止发布线程(在主线程时)。
ThreadMode.MAIN
订阅者将在Android的主线程(有时称为UI线程)中调用。如果发布线程是主线程,则将直接调用事件处理程序方法(与ThreadMode.POSTING所描述的同步)。使用此模式的事件处理程序必须快速返回以避免阻塞主线程。
ThreadMode: MAIN_ORDERED
订阅者将在Android的主线程中调用。该事件总是排队等待以后交付给订阅者,因此对post的调用将立即返回。这为事件处理提供了更严格且更一致的顺序(因此名称为MAIN_ORDERED)。例如,如果您在具有MAIN线程模式的事件处理程序中发布另一个事件,则第二个事件处理程序将在第一个事件处理程序之前完成(因为它是同步调用的 - 将其与方法调用进行比较)。使用MAIN_ORDERED,第一个事件处理程序将完成,然后第二个事件处理程序将在稍后的时间点调用(一旦主线程具有容量)。使用此模式的事件处理程序必须快速返回以避免阻塞主线程
ThreadMode:ASYNC
事件处理程序方法在单独的线程中调用。这始终独立于发布线程和主线程。发布事件永远不会等待使用此模式的事件处理程序方法。如果执行可能需要一些时间,例如事件处理程序方法应使用此模式。用于网络访问。避免同时触发大量长时间运行的异步处理程序方法来限制并发线程数。 EventBus使用线程池从已完成的异步事件处理程序通知中有效地重用线程。
ThreadMode:BACKGROUND
订阅者将在后台线程中调用。如果发布线程不是主线程,则将在发布线程中直接调用事件处理程序方法。如果发布线程是主线程,则EventBus使用单个后台线程,该线程将按顺序传递其所有事件。使用此模式的事件处理程序应尝试快速返回以避免阻塞后台线程
优点:开销小,代码更优雅、简洁,解耦发送者和接收者,可动态设置事件处理线程和优先级。
缺点:每个事件必须自定义一个事件类,增加了维护成本。