Android 淺析EventBus (一) 使用
前言
Linus Benedict Torvalds : RTFSC – Read The Fucking Source Code
概括
EventBus is a publish/subscribe event bus optimized for Android.
EventBus 是一個為 Android 優化的 publish/subscribe 事件總線。
- 簡化組件間的通訊。
- 事件發送者和接收者解耦。
- 很好地執行活動,片段和背景線程,避免復雜和容易出錯的依賴關系和生命周期的問題,使您的代碼更簡單
- 快速
- 小(大約50K)
使用
Step 1: 定義事件
Events are POJO (plain old Java object) without any specific requirements.
public class MessageEvent {
public final String message;
public MessageEvent(String message) {
this.message = message;
}
}
Step 2: 準備訂閱者
訂閱者要實現一個接口函數onEvent
,用來在收到通知后作出響應。這需要注冊到EventBus里。
@Override
public void onStart() {
super.onStart();
EventBus.getDefault().register(this);
}
@Override
public void onStop() {
EventBus.getDefault().unregister(this);
super.onStop();
}
// This method will be called when a MessageEvent is posted
public void onEvent(MessageEvent event){}
// This method will be called when a SomeOtherEvent is posted public void onEvent(SomeOtherEvent event){}
Step 3: 發送通知
發送通知可以在代碼的任意一個地方。
EventBus.getDefault().post(new MessageEvent("Hello everyone!"));
主要類解析
EventBus
EventBus is a central publish/subscribe event system for Android. Events are posted (post(Object)) to the bus, which delivers it to subscribers that have a matching handler method for the event type. To receive events, subscribers must register themselves to the bus using register(Object). Once registered, subscribers receive events until unregister(Object) is called. By convention, event handling methods must be named "onEvent", be public, return nothing (void), and have exactly one parameter (the event).
EventBus的介紹本身就很清楚了。它是一個Android的發布/訂閱事件系統。
EventBus 類負責所有對外暴露的 API,其中的 register()、post()、unregister() 函數配合上自定義的 EventType 及事件響應函數即可完成核心功能。
EventBus可以通過getDefault來獲取單例,也可以自己通過創建或者EventBusBuilder來新建一個,不過EventBus是相互隔離的。huo zh
getDefault()
進程中創建一個EventBus的單例返回。
register(Object subscriber)
注冊一個訂閱者到接收事件。訂閱者必須調用'unregister()'當它們不再接收事件。
訂閱者有一個事件句柄方法用他們的名字識別,通常是叫“onEvent”。事件句柄方法必須有一個參數,事件。如果事件句柄方法被調用在一個特殊的線程,一個修改將被用到方法的名字上。有效的修改符合ThreadMode枚舉之一。例如,如果一個方法被調用在由EventBus在UI/主線程,這將被稱為“onEventMainThread”。
unregister(Object subscriber)
反注冊一個訂閱者
post(Object event)
發送一個事件到event bus。
四種訂閱函數
- onEvent:如果使用onEvent作為訂閱函數,那么該事件在哪個線程發布出來的,onEvent就會在這個線程中運行,也就是說發布事件和接收事件線程在同一個線程。使用這個方法時,在onEvent方法中不能執行耗時操作,如果執行耗時操作容易導致事件分發延遲。
- onEventMainThread:如果使用onEventMainThread作為訂閱函數,那么不論事件是在哪個線程中發布出來的,onEventMainThread都會在UI線程中執行,接收事件就會在UI線程中運行,這個在Android中是非常有用的,因為在Android中只能在UI線程中跟新UI,所以在onEvnetMainThread方法中是不能執行耗時操作的。
- onEvnetBackground:如果使用onEventBackgrond作為訂閱函數,那么如果事件是在UI線程中發布出來的,那么onEventBackground就會在子線程中運行,如果事件本來就是子線程中發布出來的,那么onEventBackground函數直接在該子線程中執行。
- onEventAsync:使用這個函數作為訂閱函數,那么無論事件在哪個線程發布,都會創建新的子線程在執行onEventAsync.
EventBusBuilder
Creates EventBus instances with custom parameters and also allows to install a custom default EventBus instance.
Builder對應的就是Builder生成器模式。EventBusBuilder用于在需要設置參數過多時構造 EventBus。包含的屬性也是 EventBus 的一些設置參數。
build()
生成一個EventBus基于現有的配置。
SubscriberMethod
訂閱者事件響應函數信息,包括響應方法、線程 Mode、事件類型以及一個用來比較 SubscriberMethod 是否相等的特征值 methodString 共四個變量
其中 methodString 為 ${methodClassName}#${methodName}(${eventTypeClassName}。
Subscription
訂閱者信息,包括 subscriber 對象、事件響應方法 SubscriberMethod、優先級 priority。
HandlerPoster
事件主線程處理,對應ThreadMode.MainThread。繼承自 Handler,enqueue 函數將事件放到隊列中,并利用 handler 發送 message,handleMessage 函數從隊列中取事件,invoke 事件響應函數處理。
AsyncPoster
事件異步線程處理,對應ThreadMode.Async,繼承自 Runnable。enqueue 函數將事件放到隊列中,并調用線程池執行當前任務,在 run 函數從隊列中取事件,invoke 事件響應函數處理。
BackgroundPoster
事件 Background 處理,對應ThreadMode.BackgroundThread,繼承自 Runnable。enqueue 函數將事件放到隊列中,并調用線程池執行當前任務,在 run 函數從隊列中取事件,invoke 事件響應函數處理。
與 AsyncPoster.java 不同的是,BackgroundPoster 中的任務只在同一個線程中依次執行,而不是并發執行。
PendingPost
訂閱者和事件信息實體類,并含有同一隊列中指向下一個對象的指針。通過緩存存儲不用的對象,減少下次創建的性能消耗。
PendingPostQueue
通過 head 和 tail 指針維護一個PendingPost隊列。HandlerPoster、AsyncPoster、BackgroundPoster 都包含一個此隊列實例,表示各自的訂閱者及事件信息隊列,在事件到來時進入隊列,處理時從隊列中取出一個元素進行處理。
NoSubscriberEvent
當沒有事件處理函數對事件處理時發送的 EventBus 內部自定義事件,通過 post 發送,訂閱者可自行訂閱這類事件進行處理。
ThreadMode
線程 Mode 枚舉類,表示事件響應函數執行線程信息
包括:
1.ThreadMode.PostThread
2.ThreadMode.MainThread
3.ThreadMode.BackgroundThread
4.ThreadMode.Async