27、Android--EventBus
事件匯流排
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);
}
}
我們在未註冊的情況下直接傳送粘性事件後再註冊來接收即可。