首先我來解釋一下什么是事件總線模式。提到事件總線模式你可能很陌生,不知道是什么,那么我們換個說法,軟件設計模式中有一種叫做觀察者模式,其實事件總線模式就是對觀察者模式的一種實現,它是一種集中式事件處理機制,允許不同的組件之間進行彼此通信而又不需要相互依賴,達到一種解耦的目的,他就是對觀察者模式的一種拓展。如果你對觀察者模式不太熟悉的話,建議自己找找資料理解一下。接下來我通過Android里面的機制來講解一下事件總線模式。
在Android開發中,經常會涉及Activity,Fragment,Service等不同組件或者模塊之間的消息傳遞。使用傳統的方法實現,往往代碼不夠優雅,而且不同組件和模塊之間的耦合嚴重。隨着模塊的增多、代碼邏輯的不斷新增和修改,整個代碼的架構就會顯得越來越混亂。Activity中的不同的fragment之間需要進行通信,傳統的做法是 將activity作為中介,Fragment A通過getActivity()獲取宿主的Activity實例進而可以拿到Fragment B的實例,從而向Fragment B發送消息或者獲取數據。好一點的做法是在Fragment中編寫接口,讓宿主Activity實現該接口,從而在Activity中實現不同Fragment之間的數據通信。或者多個Activity頁面跳轉和數據回傳的問題,例如Activity A跳轉到Activity B,接着跳轉到ActivityC,在C中執行一系列操作之后,需要傳遞數據或者事件給Activity A,傳統的做法是進行接口回調,這樣不僅增加邏輯復雜性,而且增大頁面間的耦合。
發布者Publisher:發布某種事件的對象。
事件Event:一個簡單的POJO對象。只包含數據,不對數據進行處理。
事件總線EventBus: 負責訂閱者,事件等信息的存儲,同時處理事件的流動和分發,通過總線,訂閱者和發布者是解耦的,互相不知道對方的存在。
訂閱者Subscriber: 訂閱某種類型事件的對象。通常會有一個回調函數用於對接收到的事件進行處理,訂閱者可以訂閱事件,也可以去掉訂閱的事件。訂閱者可以引入優先級的概念,優先級高的訂閱者可以優先接收到該事件,並可以決定是否繼續傳遞事件給低優先級的訂閱者。
EventBus一共提供了4種線程模型ThreadModel,分別是PostThread, MainThread, BackgroundThread, Async。
PostThread --------------默認實現,執行發生在發布事件的同一個線程;
MainThread --------------執行在UI主線程上;
BackgroundThread、Async---兩個都是通過Executors.newCachedThreadPool()線程池來執行的。
Eventbus作為android開發中的常用框架,擁有着許多優點:
調度靈活:不依賴於Context,使用時無需像廣播一樣關注Context的注入與傳遞。父類對於通知的監聽和處理可以繼承給子類。這對於簡化代碼至關重要。通知的優先級,能夠保證Subscriber關注最重要的通知;粘滯事件能夠保證通知不會因Subscriber的不在場而忽略。 可繼承,優先級,粘滯是eventBus比之於廣播,觀察者等方式最大的優點,他們使得創建結構良好組織緊密的通知系統成為可能。
使用簡單:Eventbus的Subscriber注冊非常簡單,調用eventBus對象的register方法即可,如果不想創建eventBus還可以直接調用靜態方法EventBus.getDefault()獲取默認實例,Subscriber接收到通知之后的操作放在onEvent方法里就行了。成為Publisher的過程更簡單,只需要調用合適的eventBus(自己創建或者是默認的)的post方法即可。
快速且輕量:觀察者這種設計模式應該屬於程序員的基本功,由於觀察者的實現比較簡單,因此性能上是三者中最好的,但是觀察者難以控制通知的優先度,特別是一開始沒有考慮優先度中途更高需求又加入優先度。另外觀察者模式要求觀察者在事件發生時在場才能收到通知,這就是的觀察者有可能遺漏事件。客觀來說,這並不能算觀察者的缺點,因為其他的方式往往也是這樣,更加嚴謹的說法是觀察者沒有Eventbus優先級、粘滯事件的優點。但有一個缺點是觀察者獨有的,那就是觀察者可能會造成接口的膨脹,特別是當程序要求大量形式各異的通知,而程序員沒有做出良好的抽象時,代碼中會包含大量的接口。