天天看點

Eventbus 粘性事件 滞後傳遞資料。activity間傳大資料

項目中遇到activity傳大資料集合。使用EventBus滞後傳統的功能。網上找到的阿裡開發手冊的内容 。記錄筆記。

阿裡給出的方案,是通過 EventBus 來傳遞資料。

 EventBus 的 粘性事件

很多商業項目其實都用到了 EventBus,這裡就簡單介紹如何使用 EventBus 的粘性事件來完成資料在 Activity 間的傳遞。

EventBus 是一個 Android 端優化的 Publish/subscribe 消息總線,簡化了應用程式内各個元件間、元件與背景線程間的通信。

在 Activity 中使用 EventBus,需要根據 Activity 的生命周期,成對調用 register() 和 unregister() 方法。普通的事件,隻會發生在 register() 之後,在注冊前發生的事件,統統都收不到。

這裡利用的 EventBus 的粘性事件(Sticky Event)來實作,EventBus 内部維護了一個 Map 對象 stickyEvents,用于緩存粘性事件。

粘性事件使用 postSticky() 方法發送,它會将事件緩存到 stickyEvents 這個 Map 對象中,以待下次注冊時,将這個事件取出,抛給注冊的元件。以此來達到一個粘性的滞後事件發送和接收。

接下來我們看看 EventBus 粘性事件的使用細節。

1. 注解的差別

粘性事件的注解和普通事件的注解略有差別,需要添加 threadMode 和 sticky 參數。

@Subscribe(threadMode = ThreadMode.MAIN,sticky = true)

publicvoidonStickyEvent(MyStickyEvent event){

//...

}

注意,這兩個額外的參數是必須的。

2. 調用方法的差別

在發送消息的時候,需要使用 postSticky() 來替換掉 post() 方法。

需要注意的是,粘性事件是使用 Map 結構緩存的,并且是使用事件對象類型當 Key 進行緩存,是以對于同類型的資料,它隻會緩存最後發送的資料。

3. 注意清理事件

前面也提到,粘性事件是存儲在一個 Map 對象中的,它是不會主動清理其中存儲的對象的,需要開發者手動清理。

EventBus 提供了兩類方法 removeStickyEvent() 和 removeAllStickyEvents() 方法,分别用來清理固定資料以及全部資料。

我們需要在合适的時機,手動的調用這兩類方法,清理粘性事件。如果不對粘性事件進行清理,每次 register() 的時候,都會收到粘性事件。

4. EventBus 粘性事件的問題

粘性事件本身是脫離了 Android Intent 資料傳遞的這一套機制的,要知道 Activity 會在一些特殊情況下被銷毀重建,在此情況下,通過 Intent 傳遞的資料,是可以繼續從 Intent 中擷取恢複到上一次頁面傳遞的資料。

而通過 EventBus 的粘性事件,則可能在銷毀重建時,造成資料丢失。

如果想要使用 EventBus 的粘性事件,來在頁面間傳遞大資料,還是有不少細節,需要根據業務來調整的。

四、小結時刻

今天我們聊到了在 Activity 間,通過 Intent 傳遞大資料會觸發 TransactionTooLargeException 異常的原因,以及如何解決它,最後再簡單總結一下。

  1. Intent 無法傳遞大資料是因為其内部使用了 Binder 通信機制,Binder 事務緩沖區限制了傳遞資料的大小。
  2. Binder 事務緩沖區的大小限定在 1MB,但是這個尺寸是共享的,也就是并不是傳遞 1MB 以下的資料就絕對安全,要視目前的環境而定。
  3. 不要挑戰 Intent 傳遞資料大小的極限,對于大資料,例如長字元串、Bitmap 等,不要考慮 Intent 傳遞資料的方案。
  4. 解決大資料傳遞問題,可以從資料源出發,根據資料的辨別,還原資料,或者先持久化再還原。也可以使用 EventBus 的粘性事件來解決。