Android EventBus你需要了解的都在這
什麼是EventBus
EventBus是一個Android事件發佈/訂閱的輕量級框架,基於觀察者模式,將事件的接收者和發送者分離,主要是替代intent,Handler,BroadCast在Fragment,activity,service線程之間傳遞消息。作爲GitHub上的人氣開源項目,截止現在(2020-04-26)已經有22.4k個start。
集成
implementation 'org.greenrobot:eventbus:3.1.1'
Event基本用法
Event的用法非常簡介,一般我們使用分爲五個步驟:
- 定義一個事件類
public class MessageEvent{
···
}
- 訂閱事件
EventBus.getDefault().register(this);
- 發送事件
EventBus.getDefault().post(new MessageEvent())
- 處理事件
@Subscribe(threadMode = ThreadMode.MAIN)
fun XXX(MessageEvent messageEvent){
···
}
方法名可以隨意取,但需要添加一個@Subscribe註解,註解中ThreadMode.MAIN是指定運行在主線程中的線程模型,這個後面細講。
- 註銷訂閱事件
EventBus.getDefault().unregister(this);
EventBus應用舉例
public class MainActivity extends AppCompatActivity {
//第一個界面
private TextView tv_message;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
EventBus.getDefault().register(this);//註冊
tv_message = findViewById(R.id.tv_message);
findViewById(R.id.bn_main).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
startActivity(new Intent(MainActivity.this,SecondActivity.class));
}
});
}
@Subscribe(threadMode = ThreadMode.MAIN)//需要加上註解
public void onEventMainThred(MyEvent event){
tv_message.setText(event.getEvent())
}
@Override
protected void onDestroy() {
super.onDestroy();
EventBus.getDefault().unregister(this);//註銷
}
}
//第二個界面
public class SecondActivity extends Activity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.bn_main).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
MyEvent myEvent = new MyEvent();
myEvent.setEvent("hello");
EventBus.getDefault().post(myEvent);
finish();
}
});
}
}
//消息源
public class MyEvent {
private String event;
public String getEvent() {
return event;
}
public void setEvent(String event) {
this.event = event;
}
}
在SecondActivity的按鈕點擊事件中,點擊後回到MainActivity,並且MainActivity中的TextView
的內容也變成了hello。
從這個例子中,可以看出:EventBus的功能類似於觀察者模式和廣播,但是比起重量級的廣播,EventBus減少了複雜的調用和對象序列化的開銷,並且解耦了發佈者和訂閱者之間的關係,在代碼結構上也更加清晰簡單。
EventBus的三要素
- Event:事件,它可以是任意類型,EventBus會根據事件類型進行全局的通知。
- Subscriber:事件訂閱者,在EventBus 3.0之前我們必須定義以onEvent開頭的那幾個方法,分別是onEvent、onEventMainThread、onEventBackgroundThread和onEventAsync,而在3.0之後事件處理的方法名可以隨意取,不過需要加上註解@subscribe,並且指定線程模型,默認是POSTING。
- Publisher:事件的發佈者,可以在任意線程裏發佈事件。一般情況下,使用EventBus.getDefault()就可以得到一個EventBus對象,然後再調用post(Object)方法即可。
EventBus的四種線程模型
EventBus的線程模型就是我們在事件訂閱時,在Subscriber註解中設置的變量,其中:
- POSTING:默認,表示事件處理函數的線程跟發佈事件的線程在同一個線程。
- MAIN:表示事件處理函數的線程在主線程(UI)線程,因此在這裏不能進行耗時操作。
- BACKGROUND:表示事件處理函數的線程在後臺線程,因此不能進行UI操作。如果發佈事件的線程是主線程(UI線程),那麼事件處理函數將會開啓一個後臺線程,如果果發佈事件的線程是在後臺線程,那麼事件處理函數就使用該線程。
- ASYNC:表示無論事件發佈的線程是哪一個,事件處理函數始終會新建一個子線程運行,同樣不能進行UI操作。
EventBus的粘性事件
EventBus除了可以發送普通事件,還可以支持發送粘性事件,就是先發送事件之後再訂閱事件也能收到該事件,類似於粘性廣播,示例代碼如下:
1.訂閱者處理粘性事件
@Subscribe(threadMode = ThreadMode.MAIN, sticky = true)
fun XXX(MessageEvent messageEvent){
···
}
2.發送粘性事件
EventBus.getDefault().postSticky(new MessageEvent())
代碼經過這樣的處理,就可以先發送事件,在訂閱事件EventBus.getDefault().register(this);
時,進行事件處理。
EventBus的優先級
在Subscribe註解中總共有3個參數,上面我們用到了其中的兩個,這裏我們使用以下第三個參數,即priority
。它用來指定訂閱方法的優先級,是一個整數類型的值,默認是0,值越大表示優先級越大。在某個事件被髮布出來的時候,優先級較高的訂閱方法會首先接受到事件。
爲了對優先級進行測試,這裏我們需要對上面的代碼進行一些修改。這裏,我們使用一個布爾類型的變量來判斷是否應該取消事件的分發。我們在一個較高優先級的方法中通過該布爾值進行判斷,如果未true就停止該事件的繼續分發,從而通過低優先級的訂閱方法無法獲取到事件來證明優先級較高的訂閱方法率先獲取到了事件。