事件总线
EventBus
EventBus是一款针对Android优化的发布-订阅事件总线。它简化了应用程序内各组件间、组件与后台线程间的通信。其优点是开销小,代码更优雅,
以及将发送者和接收者解耦。
使用EventBus之前首先需要添加依赖:
implementation 'org.greenrobot:eventbus:3.1.1'
EventBus的混淆规则如下所示:
-keepattributes *Annotation*
-keepclassmembers class ** {
@org.greenrobot.eventbus.Subscribe <methods>;
}
-keep enum org.greenrobot.eventbus.ThreadMode { *; }
# Only required if you use AsyncExecutor
-keepclassmembers class * extends org.greenrobot.eventbus.util.ThrowableFailureEvent {
<init>(java.lang.Throwable);
}
使用EventBus
在使用EventBus之前,我们需要了解 EventBus 的三要素以及它的 4 种ThreadMode。
EventBus的三要素如下。
Event:事件。可以是任意类型的对象。
Subscriber:事件订阅者。在 EventBus 3.0 之前消息处理的方法只能限定于 onEvent、onEventMainThread、onEventBackgroundThread和onEventAsync,
它们分别代表4种线程模型。而在EventBus3.0之后,事件处理的方法可以随便取名,但是需要添加一个注解@Subscribe,并且要指定线程模型(默认为POSTING)。
Publisher:事件发布者。可以在任意线程任意位置发送事件,直接调用 EventBus 的post(Object)方法。
EventBus的4种ThreadMode(线程模型)如下
POSTING(默认):该事件是在哪个线程发布出来的,事件处理函数就会在哪个线程中运行。
MAIN:事件的处理会在UI线程中执行。事件处理的时间不能太长,长了会导致ANR。
BACKGROUND:事件在UI线程发布,事件处理则会在新的线程中;事件本来在子线程发布,事件处理会在发布事件的线程中。(禁止更新UI)
ASYNC:无论事件在哪个线程中发布,该事件处理函数都会在新建的子线程中执行。(禁止更新UI)
EventBus基本用法
EventBus使用起来分为如下5个步骤:
1) 自定义一个事件类
public class MessageEvent {
private String message;
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
- 在需要订阅事件的地方注册事件
EventBus.getDefault().register(this);
- 发送事件,传递的参数为定义好的事件类
MessageEvent messageEvent = new MessageEvent();
messageEvent.setMessage("Hello EventBus");
EventBus.getDefault().post(messageEvent);
- 处理事件,消息处理的方法可以随便取名,但是需要添加一个注解@Subscribe,并且要指定线程模型
@Subscribe(threadMode = ThreadMode.MAIN)
public void eventBusOnUI(MessageEvent event) {
Toast.makeText(MainActivity.this, event.getMessage(), Toast.LENGTH_SHORT).show();
}
- 取消事件订阅
EventBus.getDefault().unregister(this);
EventBus粘性事件
在activity_main.xml中编写如下布局:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:layout_centerInParent="true"
android:orientation="vertical">
<Button
android:id="@+id/btn_post"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="发送粘性事件" />
<Button
android:id="@+id/btn_regist"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="注册粘性事件"/>
</LinearLayout>
</RelativeLayout>
在MainActivity.java中加入如下代码:
public class MainActivity extends AppCompatActivity {
private Button mBtnPost;
private Button mBtnRegist;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mBtnPost = findViewById(R.id.btn_post);
mBtnRegist = findViewById(R.id.btn_regist);
// 发送粘性事件
mBtnPost.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
MessageEvent messageEvent = new MessageEvent();
messageEvent.setMessage("粘性事件");
EventBus.getDefault().postSticky(messageEvent);
}
});
// 注册粘性事件
mBtnRegist.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
EventBus.getDefault().register(MainActivity.this);
}
});
}
@Subscribe(threadMode = ThreadMode.MAIN, sticky = true)
public void onMoonStickEvent(MessageEvent event) {
Toast.makeText(MainActivity.this, event.getMessage(), Toast.LENGTH_SHORT).show();
}
@Override
protected void onDestroy() {
super.onDestroy();
EventBus.getDefault().unregister(this);
}
}
我们在未注册的情况下直接发送粘性事件后再注册来接收即可。