AndroidEventBus教程

每一次探索都源於好奇

一、說明

本系列主要是講一些開源框架的使用,幫助程序員更好更快的使用開源框架,以下內容出於本人對框架的理解,如果有不對或者不準確的地方請評論,謝謝。
我比較喜歡帶着問題去研究東西,所以我列出以下幾個問題,希望你們一樣可以帶着疑問去看,問題如下:

二、問題:

  1. AndroidEventBus是什麼?
  2. 它和EventBus以及OTTO有什麼關係,又有什麼區別?
  3. 它修復集合傳遞的問題了嗎?
  4. 粘性事件是指的什麼?如何使用?

三、細節:

下面我們來依次講解以下,首先來說什麼是AndroidEventBus:

1.AndroidEventBus 的定義

這個是它自身的定位:這是一個Android平臺的事件總線框架, 它簡化了Activity、Fragment、Service等組件之間的交互,很大程度上降低了它們之間的耦合,使得我們的代碼更加簡潔,耦合性更低,提升我們的代碼質量。
確實,通過我的使用感覺確實比官方的傳遞方式好用且方便了很多。

2.AndroidEventBus和EventBus以及OTTO之間的區別

我們先看一下下面的這個表格

名稱 訂閱函數是否可執行在其他線程 特點
greenrobot的EventBus 使用name pattern模式,效率高,但使用不方便。
square的otto 使用註解,使用方便,但效率比不了EventBus。
AndroidEventBus 使用註解,使用方便,但效率比不上EventBus。訂閱函數支持tag(類似廣播接收器的Action)使得事件的投遞更加準確,能適應更多使用場景。

  • 這個比對的是Eventbus 2.x 系列的,EventBus 3.0 的已經使用註解了,而且還可以新增了粘性事件,事件優先級,根據優先級攔截消息等功能,但是仍舊不支持tag,或者分組操作,這個對我來說是痛點,所以暫時不使用EventBus3.0

  • 我們可以看到EventBus2.x 的時候使用的固定的方法名稱(onEvent開頭的方法,不太瞭解的自行百度,或者等我出這方面的文章),速度較快,且可以切換線程。

  • OTTO 和AndroidEventBus 都是使用註解,這樣就避免了使用固定的方法名稱,但OTTO不能切換線程,AndroidEventBus 擁有OTTO 的優點而且還可以通過設置tag進行分組,解決了在同一個類下面,相同的接收參數也可以正常接收的問題,不必要去封裝多餘的類。不過它倆都是用的是註解效率就稍微差一點。我測試的AndroidEventBus 的速度還是可以接受的。

  • 共同點是他們都需要通過匹配類型傳遞,就是你post的對象和你接受的方法的參數需要一致。

3.AndroidEventBus並沒修復集合傳遞的問題

  • 首先我們先描述以下問題,具體情形是這樣的,假設你現在要發送的是個List<String> stringList 對象,且接收方法有多個,其中一個的參數是List<Long> test 而另一個的是List<String> test,這個時候我們希望的是第二個能接收到,而第一個不能接收到,但事實上兩個都可以接收到。

  • 所以我們傳遞類似的集合(List、Map)的對象的時候可以通過獲取其中的一個對象通過instanceOf判斷類型,也可以將其封裝成對應命名的xxEvent,將其作爲參數傳遞。

4.粘性事件

  • 首先我們說一下什麼是粘性事件,粘性事件指事件消費者在事件發佈之後才註冊的也能接收到該事件的特殊類型。Android中就有這樣的實例,也就是粘性廣播。正常情況下如果發送者發送了某個廣播,而接收者在這個廣播發送後才註冊自己的Receiver,這時接收者便無法接收到剛纔的廣播,爲此Android引入了粘性廣播,在廣播發送結束後會保存剛剛發送的廣播(Intent),這樣當接收者註冊完Receiver後就可以接收到剛纔已經發布的廣播。這就使得我們可以預先處理一些事件,讓有消費者時再把這些事件投遞給消費者。

  • 這種情形非常多見,比如我們在跳轉activity時,且要傳遞給下一個activity數據,這個時候我們大多數都是採用序列化的方式,將其存儲到Intent 中然後傳遞,然後下一個activity接收後再解析數據。這種情況下,爲了實現序列化就需要寫一大堆的模式代碼。而僅僅是爲了傳遞一個變量。當然也有其他的辦法,比如存儲到內存中,但這種方法維護複雜,需要及時清除。

  • 粘性事件將解決我們的痛點,我們可以在當前Activity 中發送粘性事件,然後當下一個Activity註冊後就可以接收到此事件,所以可以通過它來傳遞。

  • 需要注意的幾點如下:

    1. 當上一個activity發送一般事件和粘性事件的時候,下一個activity即使兩種都進行了註冊,很明顯只有粘性事件可以接收到消息(因爲有消息後才註冊)。

    2. 當跳轉到下一個activity的時候,這時候假設上一個activity已經註冊了一般事件和粘性事件,此時下一個activity進行發送一般事件和粘性事件的時候上一個activity(因爲註冊後纔有的消息)只有一般事件才能接收到,這樣也就確定了傳遞方向和具體的使用方法。

  • 需要注意的是粘性事件需要移除操作否則會一直存在。

5.代碼怎麼寫?

  • 首先對於一般的事件發送方的操作如下:
    EventBus.getDefault().post(Object) ,這個是不使用tag 的發送代碼。
    EventBus.getDefault().post(Object, tag), 這個是使用tag的發送代碼
    這個地方可以這麼理解第一種使用的是默認tag,第二種是你自定的tag,只有參數和tag 能對應,對應的接收方法才能接收到

  • 對於一般消息的接收方做如下操作:
    EventBus.getDefault().register(this) 首先在onCreate 方法中使用這個方法進行註冊。
    EventBus.getDefault().unregister(this) 然後在onDestroy方法中使用這個方法反註冊。

    接收方的接收方法有如下幾種類型:

 // 接收方法,默認的tag,執行在UI線程
    @Subscriber
    private void updateUser(User user) {
        Log.e("", "### update user name = " + user.name);
    }

    // 含有my_tag,當用戶post事件時,只有指定了"my_tag"的事件纔會觸發該函數,執行在UI線程
    @Subscriber(tag = "my_tag")
    private void updateUserWithTag(User user) {
        Log.e("", "### update user with my_tag, name = " + user.name);
    }

    // 含有my_tag,當用戶post事件時,只有指定了"my_tag"的事件纔會觸發該函數,
    // post函數在哪個線程執行,該函數就執行在哪個線程    
    @Subscriber(tag = "my_tag", mode=ThreadMode.POST)
    private void updateUserWithMode(User user) {
        Log.e("", "### update user with my_tag, name = " + user.name);
    }

    // 含有my_tag,當用戶post事件時,只有指定了"my_tag"的事件纔會觸發該函數,執行在一個獨立的線程
    @Subscriber(tag = "my_tag", mode = ThreadMode.ASYNC)
    private void updateUserAsync(User user) {
        Log.e("", "### update user async , name = " + user.name + ", thread name = " + 
    }
  • 對於粘性事件發送方的操作如下:

EventBus.getDefault().postSticky(Object, tag)
EventBus.getDefault().postSticky(Object)

理解方式同一般事件。

  • 對於接收方的操作如下:

EventBus.getDefault().registerSticky(this) 首先在onCreate中使用此代碼註冊

它對於事件的接收同一般事件是一樣的,不再贅述。

另一個和一般事件不同,它不需要反註冊,但是它需要銷燬粘性事件,否則粘性事件會一直存在。
銷燬代碼如下:

EventBus.getDefault().removeStickyEvent(String.class, "registerSticky"); //前面是class,後面是對應的tag。銷燬對應類型(Class)的,對應tag的粘性事件。
EventBus.getDefault().removeStickyEvent(String.class); //銷燬對應類型的,默認tag的粘性事件

需要注意銷燬的時機,可以是接收後,也可以是onStop或者onDestroy,根據自身需求定。

經測試粘性事件的接收函數在主線程中的,可以用於更新UI,也就是說,事件傳遞是在UI加載完成後的。


自此分析完畢,如果想了解更多其他的框架或者文中提到的框架,請觀看本博客的其他內容,後續會加入鏈接。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章