近來在看平凡的世界,一發不可收拾,非常震撼心靈,心里面的那種觸動我真的表達不清楚。已經很久沒有看到這么好看的電視劇了。如果你還沒看過,我推薦大家可以去看一看。
前段時間有人問我,fragment 怎么與 activity 通信?同級下的 fragment 之間的通信?
對于這個問題有很多方案,我簡單的說幾種,可能還有更好的方案。
宿主 onAttach 方法獲取到 activity 實例,有了實例就是調用方法的問題了。注意不同的 fragment 之間需要強轉。
接口
廣播 (有點大題小用了)
handler
EventBus,RxBus,Otto
五種方案各有優缺點,在項目當中根據具體情況靈活應用。這里主要講解 EventBus 在項目中的使用,雖然 EventBus 可以很方便的實現模塊與模塊之間的通信,如果頻繁的使用可能導致代碼錯亂。這點對于初學者尤為重要。下面一起來看看 EventBus 一些常用的使用方法。
EventBus是一個 發布/訂閱 模式的消息總線庫,它簡化了應用程序內各組件間、組件與后臺線程間的通信,解耦了事件的發送者和接收者,避免了復雜的、易于出錯的依賴及生命周期問題,可以使我們的代碼更加簡潔、健壯。EventBus 用于各組件通信,那么用于 fragment 之間的通信就非常合適了。
相關文章:
初談一java Annotation
EventBus的github地址
項目依賴
gradle依賴:
在 app 的 build.gradle文件下:
接著來擼一擼 EventBus 的使用步驟:
1、 定義事件2、 訂閱3、 發布事件MessageEvent 為例:
public class MessageEvent { public String message; public MessageEvent(String message) { this.message = message; }}聲明訂閱方法,并且指定線程模式(默認主線程)。
@Subscribe(threadMode = ThreadMode.MAIN) public void onMessageEvent(MessageEvent event) { Toast.makeText(this,"你好EventBus"+event.message,Toast.LENGTH_SHORT).show(); };注意 @Subscribe annotation 是不可缺少的,onMessageEvent方法名可以隨意命名。
在 activity 或 fragment 注冊和注銷 EventBus:
onCreate注冊:
onStart注冊:
onDestroy注銷:
最后即是事件源發布事件。我們可以在代碼的任何位置發布事件,當前所有事件類型與發布的事件類型匹配的訂閱者都將收到它。其實內部是以 map 來存儲事件,map的鍵就是事件類名(這里就是MessageEvent作為鍵值),在發布相同事件源的時候避免多次處理。
下面來看一個簡單的案例(通過點擊按鈕來發步事件源):
public void click_event(View view) { EventBus.getDefault().post(new MessageEvent("雞年大吉")); }效果圖一覽:

源碼我會在文章的最后給出。
Sticky事件被我稱之為粘性事件,功能類似sticky broadcast(粘性廣播)。就是某些事件攜帶的信息在事件被發布之后依然有價值。比如,當前 activity 發布了事件源,新啟的 activity 對該事件進行訂閱,同樣能夠處理。
發布粘性事件:
EventBus.getDefault().postSticky(new MessageEvent("大吉大利"));處理粘性事件:
@Subscribe(threadMode = ThreadMode.MAIN, sticky = true) public void onMessageEvent(MessageEvent event) { Toast.makeText(this, "接收A發來的消息" + event.message, Toast.LENGTH_SHORT).show(); }注意 sticky 成員設置為 true,默認為 false。
運行效果圖:

源碼會在文章最后附上
最新的sticky事件會在注冊時立即自動地被傳遞給匹配的訂閱者。但有時手動地去檢查sticky事件可能會更方便一些。有時也可能需要移除(消費)sticky事件以便于它不會再被傳遞。
移除sticky事件:
查看源碼我們知道removeStickyEvent方法是重載的,當傳遞class時,它將返回持有的之前的sticky事件。也可以使用如下變體進行處理:
我們可以通過優先級來改變事件傳遞的順序。
@Subscribe(priority = 1) public void onEvent(MessageEvent event) { }在相同的傳遞線程內(ThreadMode),優先級越高的訂閱者越先接收到事件。默認優先級為0。在不同線程(ThreadMode)中優先級并不會影響事件的傳遞順序。
有時我們需要取消事件的傳遞:
@Subscribe() public void onMessageEvent(MessageEvent event) { //處理事件... //取消事件 EventBus.getDefault().cancelEventDelivery(event) ; }所有后續的事件傳遞將被取消,后面的訂閱者將無法接收到事件。cancelEventDelivery方法只接收(Object event)參數,那么我們只能在訂閱者的事件處理方法中調用。
事件可以在不同于拋出事件的線程中傳遞。一個很常見的例子,獲取網絡數據更新UI。網絡,耗時的操作必然是異步操作,更新 UI 則在 UI 線程操作。
EventBus的傳遞線程類型有四類:
ThreadMode.POSTING
默認方式,訂閱者將在與拋出事件相同的線程中被調用。事件傳遞是同步完成的,事件傳遞完成時,所有的訂閱者將已經被調用了一次。這個ThreadMode意味著最小的開銷,因為它完全避免了線程的切換。鑒于以上的特點,那么可以用于已知耗時非常短的簡單的不需要請求主線程的任務,可以采用該模式。使用這個模式的事件處理器應該迅速返回以避免阻塞發布事件的線程,而后者可能是主線程。比如:
ThreadMode.MAIN
訂閱者將在主線程(UI線程)中被調用。如果發布事件的線程是主線程,事件處理器方法將會直接被調用。事件處理器使用這個模式必須快速地返回以避免阻塞主線程。
@Subscribe(threadMode = ThreadMode.MAIN) public void onMessage(MessageEvent event) { //處理事件 }ThreadMode.BACKGROUND
訂閱者將在一個后臺線程中被調用。如果發布事件的線程不是主線程,事件處理器方法將在該線程中被調用;反之,EventBus使用一個單獨的后臺線程,它將順序地傳遞它所有的事件。使用該模式的事件處理器應該嘗試快速返回以避免阻塞后臺線程。
ThreadMode.ASYNC
訂閱者將在另外一個線程中被調用。這里的另外一個線程不等同于發布事件的線程和UI線程。用于處理比較耗時的操作,如訪問網絡,數據庫操作。
EventBus 原理這里就不在深入,EventBus 真的非常棒,值得你擁有。
源碼地址
新聞熱點
疑難解答