EventBus
EventBus 是适用于 Android 和 Java 的发布/订阅事件总线。主要功能是替代 Intent、Handler、BroadCast 在 Activity、Fragment、Service 线程之间传递消息。EventBus 能够简化应用组件间的通信,解耦 (有效分离) 事件的发送者和接收者,避免复杂和容易出错的依赖和生命周期问题,开销小,代码更优雅。但是需要注意的是 EventBus 不能用于进程间通信。 Andorid 组件间通信,可能都是用 Handler 消息机制或者广播机制来实现通信,但是它们代码量大,组件上容易产生耦合 。
GitHub地址:EventBus
主要就是三个部分,一个部分是Subscriber,需要在Subscriber类中进行register和unregister操作。一部分是在Subscriber中需要创建一个方法来接收事件信息,最后一部分就是在需要发送事件的环境使用post方法来发送事件信息。这三部分中所用到的eventBus实例得要是同一个实例。
EventBus的使用
首先我们要在准备订阅事件的组件中注册订阅者。具体就是在activity的onCreate中注册,在onDestroy中注销。调用EventBus.getDefault().register()和EventBus.getDefault().unregister()方法。
接下来订阅者需要定义事件处理方法(也称为订阅者方法)。当发布对应类型的事件时,该方法将被调用。EventBus使用 @Subscribe 注解来定义订阅者方法。方法名可以是任意合法的方法名,参数类型为订阅事件的类型。
EventBus的Subscribe注解中共有3个参数,threadMode,sticky,priority。先说一下‘最后的这个参数,它用来指定订阅方法的优先级,是一个整数类型的值,默认是0,值越大表示优先级越大。在某个事件被发布出来的时候,优先级较高的订阅方法会首先接受到事件。
下面这是EventBus的使用演示:
这是在MainActivity中的发送粘性事件:
@Route(path = "/app/MainActivity")
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button button = findViewById(R.id.buttonMain);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
ARouter.getInstance().build("/module/MainActivity2")
.withString("name", "android")
.withDouble("d", 10.1)
.navigation();
EventBus.getDefault().postSticky(new EventMessage("name", 1));
}
});
}
}
public class EventMessage {
private String name;
private int age;
public EventMessage(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
这是在MainActivity2中接收订阅事件:
@Route(path = "/module/MainActivity2")
public class MainActivity2 extends AppCompatActivity {
@Autowired(name = "name")
String name;
@Autowired(name = "d")
double aDouble;
TextView textView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
textView = findViewById(R.id.text1);
ARouter.getInstance().inject(this);
}
@Override
protected void onStart() { //在onStart()或者在onCreate()中订阅事件都是可以的,官方推荐在onStart()中订阅事件
super.onStart();
EventBus.getDefault().register(this);
}
@SuppressLint("SetTextI18n")
@Subscribe(threadMode = ThreadMode.POSTING, sticky = true)
public void showEventMessage(EventMessage eventMessage) {
textView.setText(eventMessage.getName() + eventMessage.getAge());
Log.d("TAG", "showEventMessage: " + eventMessage.getName() + eventMessage.getAge());
}
@Override
protected void onDestroy() {
super.onDestroy();
EventBus.getDefault().unregister(this);
}
}
EventBus的线程模式
在刚才创建订阅方法时,注释中出现了threadMode,这就是线程模式。EventBus支持订阅者方法在不同于发布事件所在线程的线程中被调用。你可以使用线程模式来指定调用订阅者方法的线程。EventBus总共支持5种线程模式:
1.ThreadMode.POSTING
订阅者方法将在发布事件所在的线程中被调用。这是 默认的线程模式。事件的传递是同步的,一旦发布事件,所有该模式的订阅者方法都将被调用。这种线程模式意味着最少的性能开销,因为它避免了线程的切换。因此,对于不要求是主线程并且耗时很短的简单任务推荐使用该模式。使用该模式的订阅者方法应该快速返回,以避免阻塞发布事件的线程,这可能是主线程。
2.ThreadMode.MAIN
订阅者方法将在主线程(UI线程)中被调用。因此,可以在该模式的订阅者方法中直接更新UI界面。如果发布事件的线程是主线程,那么该模式的订阅者方法将被直接调用。使用该模式的订阅者方法必须快速返回,以避免阻塞主线程。
3.ThreadMode.MAIN_ORDERED
订阅者方法将在主线程(UI线程)中被调用。因此,可以在该模式的订阅者方法中直接更新UI界面。事件将先进入队列然后才发送给订阅者,所以发布事件的调用将立即返回。这使得事件的处理保持严格的串行顺序。使用该模式的订阅者方法必须快速返回,以避免阻塞主线程。
4.ThreadMode.BACKGROUND
订阅者方法将在后台线程中被调用。如果发布事件的线程不是主线程,那么订阅者方法将直接在该线程中被调用。如果发布事件的线程是主线程,那么将使用一个单独的后台线程,该线程将按顺序发送所有的事件。使用该模式的订阅者方法应该快速返回,以避免阻塞后台线程。
5.ThreadMode.ASYNC
订阅者方法将在一个单独的线程中被调用。因此,发布事件的调用将立即返回。如果订阅者方法的执行需要一些时间,例如网络访问,那么就应该使用该模式。避免触发大量的长时间运行的订阅者方法,以限制并发线程的数量。EventBus使用了一个线程池来有效地重用已经完成调用订阅者方法的线程。