EventBus使得組件之間的發佈-訂閱式的通訊,而無需組件與另外一個(所以要注意對方的),明確登記。它的設計徹底使用明確的登記,以取代傳統的Java過程當中的事件分發。它是不是一個通用的發佈-訂閱系統中,也不旨在用於進程間通訊。app
//類一般由註冊 地方在初始化過程當中 eventBus 。註冊(新 EventBusChangeRecorder ()); //要晚得多 公共 無效changeCustomer () { 的ChangeEvent 事件 = getChangeEvent (); eventBus 。後(事件); }
將現有的EventListener基於系統使用的EventBus容易。異步
偵聽事件的特定味道(好比,一個CustomerChangeEvent)...工具
註冊您的偵聽器方法的事件生產者...post
要收聽和檢測共出動,沒有聽衆的事件...測試
爲了跟蹤監聽到你的事件?ui
派遣一個事件監聽器...google
該EventBus系統代碼中使用下列術語來討論事件分發:spa
事件 | 可任意物體貼到一個總線。 |
認購 | 登記的動做偵聽器與EventBus,使得它的處理方法將得到的事件。 |
傾聽者 | 任何但願接收事件,暴露的對象處理方法。 |
處理方法 | 該公共方法EventBus應該使用提供發佈事件。處理方法的標誌是訂閱註解。 |
發佈事件 | 使得事件提供給任何聽衆經過EventBus。 |
EventBus不指定你如何使用它; 沒有什麼沒必要單獨中止你的應用程序EventBus狀況下,爲每一個組件,或者使用單獨的實例來分離上下文或主題活動。這也使得它瑣碎的創建和拆除EventBus在您的測試對象。設計
固然,若是你想有一個過程性的EventBus單身,沒有什麼從作這種方式阻止你。只需您的容器(如吉斯)建立EventBus做爲一個單身在全局範圍內(或藏在一個靜態字段,若是你到諸如此類的事情)。調試
總之,EventBus是否是單身,由於咱們寧願不做出這樣的決定你。使用它,你怎麼樣。
是的,使用EventBus.unregister,但咱們發現,只須要不多:
咱們認爲事件總線的@Subscribe註釋就像明確地傳達你的意圖是實現一個接口(或者更左右),同時使你自由,不管你但願將事件處理方法,並給他們的意圖展示的名字。
傳統的Java活動使用監聽器接口一般運動只有極少數的方法 - 一般是一個。這具備許多缺點:
在乾淨實施這一困難已經引發了一種模式,在Swing應用程序中特別常見,用微小的匿名類來實現事件監聽器接口。
比較這兩種狀況:
class ChangeRecorder { void setCustomer ( Customer cust ) { cust . addChangeListener ( new ChangeListener () { public void customerChanged ( ChangeEvent e ) { recordChange ( e . getChange ()); } }; } }
與
//類一般由註冊container. class EventBusChangeRecorder { @Subscribe public void recordCustomerChange ( ChangeEvent e ) { recordChange ( e . getChange ()); } }
其目的是在第二種狀況下竟然清晰的:有較少的噪聲碼,和事件處理程序有一個明確的和有意義的名字。
有人提出了一個通用的 處理程序<T>接口 EventBus聽衆。這將運行與Java的使用類型擦除的,更況且在可用性問題的問題。
比方說,界面看起來像下面這樣:
接口 處理器< 牛逼> { 無效的handleEvent (牛逼事件); }
因爲擦除,沒有任何一個類能夠用不一樣類型的參數實現的通用接口不止一次。這是一個巨大的倒退,從傳統的Java事件,在那裏即便 的actionPerformed和 的keyPressed都不是頗有意義的名字,至少能夠實現兩個方法!
有些人嚇壞了約EventBus的寄存器(對象)和後期(對象)的方法「使用的對象類型。
對象在這裏使用一個很好的理由:事件總線庫的地方在任您事件偵聽器的類型沒有限制(如寄存器(對象))或事件自己(在後(對象))。
事件處理方法,在另外一方面,必須明確聲明其參數類型 - 所需的事件類型(或它的超類型之一)。所以,尋找引用的事件類將當即查找全部處理方法該事件,並從新命名的類型會影響視野內的IDE(以及建立活動的任何代碼)的全部處理方法。
這是真的,你能夠重命名你@Subscribed隨意事件處理方法; 事件總線不會中止這樣或作任何事情來傳播重命名,由於,到事件總線,你的處理方法的名稱是可有可無的。可是這是你的重構工具是什麼-即直接調用,固然會受你的重命名的方法測試代碼。咱們認爲這是一個特色,不是一個錯誤:能重命名處理方法的意願讓你作本身的意思更清晰。
什麼都沒有。
事件總線的設計與容器和模塊系統集成,與吉斯做爲典型例子。在這種狀況下,它的方便的容器/工廠/環境下經過每一個建立的對象到EventBus的寄存器(對象)的方法。
這樣,經過容器/工廠/環境建立的任何對象均可以經過簡單地暴露處理方法掛接到系統的事件模型。
能夠經過Java的類型系統明確地檢測出任何問題。例如,定義一個處理方法不存在的事件類型。
緊隨調用寄存器(對象),正在註冊的偵聽器檢查的良好性,其處理方法。具體來講,標有任何方法@Subscribe必須只有一個參數。
任何違反此規則將致使拋出:IllegalArgumentException拋出。
(此檢查能夠移動使用APT,一個解決方案,咱們正在研究編譯時間。)
若是沒有註冊的偵聽器組件發佈事件,它可能會指示錯誤(一般是你錯過了一個指示@Subscribe註釋,或沒有加載監聽組件)。
(請注意,這並不必定代表有問題的。有不少狀況下,一個應用程序會故意忽略發佈的事件,特別是若是事件是從你沒法控制的代碼來了。)
爲了處理這些事件,註冊一個處理方法爲DeadEvent類。每當EventBus接收到一個事件,沒有註冊的處理程序,它會變成一個DeadEvent,並經過它本身的方式-讓你登陸,或以其餘方式收回。
由於你的監聽類處理方法都是正常的方法,你能夠簡單地從你的測試代碼中調用它們來模擬EventBus。
EventBus是專門用來對付一大類用例真的,真的很好。咱們寧願打在要害大多數用例在全部用例作體面。
此外,使得EventBus擴展-和使得它很是有用和生產上延伸,而仍容許本身做出補充到芯EventBus API,它不與任何的擴展的衝突-是一個極其困難的問題。
若是你真的,真的須要魔法的事情X,即EventBus目前沒法提供,你應該提交一個問題,而後設計本身的選擇。