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 的粘性事件來解決。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章