EventBus的使用

EventBus是一個Android平臺上的事件發(fā)送/訂閱框架,采用觀察者模式實現(xiàn),可以優(yōu)化組件間的信息傳遞過程。

這篇筆記主要參考官方文檔,點[這里][1].
[1]: https://github.com/greenrobot/EventBus/blob/master/HOWTO.md

基本的使用

1. 定義events

Events通常是一個POJO(plain old Java object).可以根據(jù)需要,隨便定義。可以定義多種類型的events,事件處理函數(shù)根據(jù)事件的類型實現(xiàn)重載。events除了自定義,還可以是Java中的基本類型(int, boolean等)。

public class MessageEvent{
    public String message;
    
    public MessageEvent(String message){
        this.message = message;
    }
}

2. 注冊訂閱者

只有需要接收events的地方,才需要注冊訂閱者。只是發(fā)送事件的話,不必注冊。
在Acitvity中注冊和注銷訂閱者:

    @Override
    public void onStart() {
        super.onStart();
        EventBus.getDefault().register(this);
    }

    @Override
    public void onStop() {
        EventBus.getDefault().unregister(this);
        super.onStop();
    }

3. 添加events處理函數(shù)

其實添加events處理函數(shù)也是注冊訂閱者的一部分,它們倆一起完成了注冊任務(wù)。
在注冊了訂閱者的地方,添加事件處理函數(shù)。

    // This method will be called when a MessageEvent is posted
    public void onEvent(MessageEvent event){
        Toast.makeText(getActivity(), event.message, Toast.LENGTH_SHORT).show();
    }

    // This method will be called when a SomeOtherEvent is posted
    public void onEvent(SomeOtherEvent event){
        doSomethingWith(event);
    }

有兩點需要注意:

  1. 事件處理函數(shù)必須有參數(shù),且只能有一個參數(shù)。函數(shù)根據(jù)這個參數(shù)的類型,實現(xiàn)重載的功能。
  2. 事件處理函數(shù)的名字必須以onEvent開頭,且必須是以下四種:
    • onEvent
    • onEventMainThread
    • onEventBackgroundThread
    • onEventAsync

4. 發(fā)送events

可以在任何地方發(fā)送一個事件。所有注冊了這個事件類型的訂閱者都可以收到它。

EventBus.getDefault().post(new MessageEvent("Hello everyone!"));

這里有兩點需要注意:

  • 如果event是基本類型,發(fā)送時event會被自動裝箱。因此事件處理函數(shù)(onEvent)的參數(shù)類型必須是基本類型對應(yīng)的對象類型。
  • 所有注冊了event對象的父類的訂閱者,都可以收到這個event。也就是說,如果某個訂閱者的某個事件處理函數(shù)的參數(shù)是Object類型

onEvent(Object object)

那么所有發(fā)出去的event,它都可以收到。

線程模型

EventBus可以自動處理線程問題,使我們從后臺線程與UI線程的切換中解放出來。

在EventBus中,通過約定事件處理函數(shù)名稱的方式,決定在哪個線程中執(zhí)行事件處理方法。

  • onEvent
    對應(yīng)PostThread模型,事件處理函數(shù)將會在事件發(fā)送者的線程上執(zhí)行。這種模式,不需要切換線程,是最快速的,推薦默認采用。
  • onEventMainThread
    對應(yīng)MainThread模型,事件處理函數(shù)將會在主線程上執(zhí)行。
  • onEventBackgroundThread
    對應(yīng)BackgroundThread模型,如果發(fā)送線程不是主線程,那么事件處理函數(shù)將會直接在發(fā)送線程調(diào)用。如果發(fā)送線程是主線程,那么EventBus會啟用一個后臺線程執(zhí)行事件處理函數(shù)。
  • onEventAsync
    對應(yīng)Async模型,EventBus會啟用一個單獨的線程(既不是發(fā)送線程,又不是主線程)執(zhí)行事件處理函數(shù)。EventBus會使用線程池,重用線程。

設(shè)定優(yōu)先級

可以在注冊的時候,設(shè)置訂閱者的優(yōu)先級。

    int priority = 1;  
    EventBus.getDefault().register(this, priority);

高優(yōu)先級的訂閱者,可以先接收到事件。默認的優(yōu)先級是0.
這里有一點需要注意,用官方文檔的話說就是:

Note: the priority does NOT affect the order of delivery among subscribers with different ThreadModes!

也就是說,兩個訂閱者:subscribe1和subscribe2,subscribe1的優(yōu)先級較高,那么subscribe1的onEvent函數(shù)肯定比subscribe2的onEvent函數(shù)先接收到事件,onEventBackgroundThread函數(shù)也肯定比subscribe2的onEventBackgroundThread優(yōu)先。但是不能比較subscribe1的onEvent和subscribe2的onEventBackgroundThread,因為它們的線程模型不同,可能在不同的線程上。

取消events的傳遞

高優(yōu)先級的訂閱者可以在事件處理函數(shù)中取消事件的傳遞。

    // Called in the same thread (default)
    public void onEvent(MessageEvent event){
        // Process the event 
        ...

        EventBus.getDefault().cancelEventDelivery(event) ;
    }

Sticky Events

Sticky Events可以用于需要延遲接收事件的情況。
普通的事件發(fā)送出去以后,EventBus便不再持有了,因此后續(xù)注冊的訂閱者無法接收到它。但是sticky事件不同,EventBus會在內(nèi)存中為每一種事件類型保存一個最新發(fā)送的事件,直到后續(xù)發(fā)送新的sticky事件,把它覆蓋掉。因此后續(xù)注冊的訂閱者,依然可以從內(nèi)存中得到這個已發(fā)送的sticky事件。
發(fā)送sticky事件:

EventBus.getDefault().postSticky(new MessageEvent("Hello everyone!"));

注冊sticky訂閱者:

    @Override
    public void onStart() {
        super.onStart();
        EventBus.getDefault().registerSticky(this);
    }

    public void onEventMainThread(MessageEvent event) {
        textField.setText(event.message);
    }

    @Override
    public void onStop() {
        EventBus.getDefault().unregister(this);
        super.onStop();
    }

也可以直接直接獲得某個類型的sticky事件:

EventBus.getDefault().getStickyEvent(Class<?> eventType)

有兩點需要注意:

  • sticky類型的訂閱者,依然可以收到普通類型的event;但是普通類型的訂閱者收不到sticky類型的event
  • 某個類型,只有最新的事件才會被保存
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容