EventBus

EventBus使得組件之間的發佈-訂閱式的通訊,而無需組件與另外一個(所以要注意對方的),明確登記。它的設計徹底使用明確的登記,以取代傳統的Java過程當中的事件分發。它是不是一個通用的發佈-訂閱系統中,也不旨在用於進程間通訊。app

//類一般由註冊 
  
     

  

地方在初始化過程當中
eventBus 註冊 EventBusChangeRecorder ()); 
//要晚得多
公共 無效changeCustomer () { 
  的ChangeEvent  事件 = getChangeEvent (); 
  eventBus 事件); 
}

將現有的EventListener基於系統使用的EventBus容易。異步

偵聽事件的特定味道(好比,一個CustomerChangeEvent)...工具

  • ......在傳統的Java事件:實現與該事件定義的接口-好比CustomerChangeEventListener
  • ...與EventBus建立一個接受的方法CustomerChangeEvent做爲其惟一的參數,並將其與標記訂閱註解。

註冊您的偵聽器方法的事件生產者...post

  • ......在傳統的Java事件:經過你的對象每一個生產者的registerCustomerChangeEventListener方法。這些方法在經常使用接口不多定義,因此除了知道每個可能的製片人,你還必須知道它的類型。
  • ...與EventBus經過你的對象給EventBus.register(對象)上的方法EventBus。你須要確保你的對象共享一個EventBus實例的事件生產者。
要收聽爲了一個共同的事件超(如 的EventObject 對象 )...
  • ......在傳統的Java事件:不容易。
  • ...與EventBus事件自動調度到任何超的聽衆,讓聽衆接口類型或「通配符聽衆」的對象

要收聽和檢測共出動,沒有聽衆的事件...測試

  • ......在傳統的Java事件:將代碼添加到每一個事件分派方法(可能使用AOP)。
  • ...與EventBus訂閱DeadEvent。該EventBus將通知被張貼,但沒有交付任何的事件。(方便的調試。)

生產者

爲了跟蹤監聽到你的事件?ui

  • ......在傳統的Java事件:寫代碼來管理聽衆的名單給你的對象,其中包括同步,或者使用相似工具類EventListenerList
  • ...與EventBus EventBus這是否適合你。

派遣一個事件監聽器...google

  • ......在傳統的Java事件:寫一個方法來分派事件到每個事件偵聽器,包括錯誤隔離和(若是須要)異步。
  • ...與EventBus事件對象傳遞給EventBusEventBus.post(對象)的方法。

詞彙表

EventBus系統代碼中使用下列術語來討論事件分發:spa

事件 可任意物體到一個總線。
認購 登記的動做偵聽器EventBus,使得它的處理方法將得到的事件。
傾聽者 任何但願接收事件,暴露的對象處理方法
處理方法 該公共方法EventBus應該使用提供發佈事件。處理方法的標誌是訂閱註解。
發佈事件 使得事件提供給任何聽衆經過EventBus

常問問題

爲何我必須建立本身的事件總線,而不是使用一個單身?

EventBus不指定你如何使用它; 沒有什麼沒必要單獨中止你的應用程序EventBus狀況下,爲每一個組件,或者使用單獨的實例來分離上下文或主題活動。這也使得它瑣碎的創建和拆除EventBus在您的測試對象。設計

固然,若是你想有一個過程性的EventBus單身,沒有什麼從作這種方式阻止你。只需您的容器(如吉斯)建立EventBus做爲一個單身在全局範圍內(或藏在一個靜態字段,若是你到諸如此類的事情)。調試

總之,EventBus是否是單身,由於咱們寧願不做出這樣的決定你。使用它,你怎麼樣。

我能夠從註銷事件總線的監聽器?

是的,使用EventBus.unregister,但咱們發現,只須要不多:

  • 大多數聽衆註冊在啓動時或延遲初始化,並堅持應用程序的生命。
  • 範圍特定EventBus實例能夠處理臨時事件分發(如分發事件中的請求範圍的對象)
  • 爲了測試,EventBus實例能夠容易地建立並扔掉,再也不須要顯式的取消註冊。

爲何要使用一個註釋標記處理方法,而不是要求聽者實現接口?

咱們認爲事件總線的@Subscribe註釋就像明確地傳達你的意圖是實現一個接口(或者更左右),同時使你自由,不管你但願將事件處理方法,並給他們的意圖展示的名字。

傳統的Java活動使用監聽器接口一般運動只有極少數的方法 - 一般是一個。這具備許多缺點:

  • 任何一個類只能實現對給定事件的單個響應。
  • 監聽器接口方法可能會發生衝突。
  • 該方法必須命名的事件(例如通過handleChangeEvent),而不是它的目的(如recordChangeInJournal)。
  • 每一個事件一般都有本身的接口,沒有一個共同的父接口,爲家庭的事件(例如,全部UI事件)。

在乾淨實施這一困難已經引發了一種模式,在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>接口?

有人提出了一個通用的 處理程序<T>接口 EventBus聽衆。這將運行與Java的使用類型擦除的,更況且在可用性問題的問題。

比方說,界面看起來像下面這樣:

接口 處理器< 牛逼>  { 
  無效的handleEvent 牛逼事件); 
}
因爲擦除,沒有任何一個類能夠用不一樣類型的參數實現的通用接口不止一次。這是一個巨大的倒退,從傳統的Java事件,在那裏即便 的actionPerformed的keyPressed都不是頗有意義的名字,至少能夠實現兩個方法!

EventBus破壞靜態類型,消除自動重構的支持?

有些人嚇壞了約EventBus寄存器(對象)後期(對象)的方法「使用的對象類型。

對象在這裏使用一個很好的理由:事件總線庫的地方在任您事件偵聽器的類型沒有限制(如寄存器(對象))或事件自己(在後(對象))。

事件處理方法,在另外一方面,必須明確聲明其參數類型 - 所需的事件類型(或它的超類型之一)。所以,尋找引用的事件類將當即查找全部處理方法該事件,並從新命名的類型會影響視野內的IDE(以及建立活動的任何代碼)的全部處理方法。

這是真的,你能夠重命名你@Subscribed隨意事件處理方法; 事件總線不會中止這樣或作任何事情來傳播重命名,由於,到事件總線,你的處理方法的名稱是可有可無的。可是這是你的重構工具是什麼-即直接調用,固然會受你的重命名的方法測試代碼。咱們認爲這是一個特色,不是一個錯誤:能重命名處理方法的意願讓你作本身的意思更清晰。

若是我發生什麼註冊一個監聽器沒有任何處理方法?

什麼都沒有。

事件總線的設計與容器和模塊系統集成,與吉斯做爲典型例子。在這種狀況下,它的方便的容器/工廠/環境下經過每一個建立的對象到EventBus寄存器(對象)的方法。

這樣,經過容器/工廠/環境建立的任何對象均可以經過簡單地暴露處理方法掛接到系統的事件模型。

什麼事件總線問題均可以在編譯時被檢測到?

能夠經過Java的類型系統明確地檢測出任何問題。例如,定義一個處理方法不存在的事件類型。

什麼事件總線問題能夠當即在註冊檢測?

緊隨調用寄存器(對象),正在註冊的偵聽器檢查的良好性,其處理方法。具體來講,標有任何方法@Subscribe必須只有一個參數。

任何違反此規則將致使拋出:IllegalArgumentException拋出。

(此檢查能夠移動使用APT,一個解決方案,咱們正在研究編譯時間。)

什麼EventBus問題能夠僅購買檢測,在運行時?

若是沒有註冊的偵聽器組件發佈事件,它可能會指示錯誤(一般是你錯過了一個指示@Subscribe註釋,或沒有加載監聽組件)。

(請注意,這並不必定代表有問題的。有不少狀況下,一個應用程序會故意忽略發佈的事件,特別是若是事件是從你沒法控制的代碼來了。)

爲了處理這些事件,註冊一個處理方法爲DeadEvent類。每當EventBus接收到一個事件,沒有註冊的處理程序,它會變成一個DeadEvent,並經過它本身的方式-讓你登陸,或以其餘方式收回。

如何測試事件偵聽器及其處理方法?

由於你的監聽類處理方法都是正常的方法,你能夠簡單地從你的測試代碼中調用它們來模擬EventBus

爲何我不能作<神奇的事情>與EventBus

EventBus是專門用來對付一大類用例真的,真的很好。咱們寧願打在要害大多數用例在全部用例作體面。

此外,使得EventBus擴展-和使得它很是有用和生產上延伸,而容許本身做出補充到芯EventBus API,它不與任何的擴展的衝突-是一個極其困難的問題。

若是你真的,真的須要魔法的事情X,即EventBus目前沒法提供,你應該提交一個問題,而後設計本身的選擇。

相關文章
相關標籤/搜索