一、默認(rèn)EventBus實(shí)例
當(dāng)某個(gè)類(lèi)需要訂閱事件時(shí),我們通常會(huì)先在這個(gè)類(lèi)的某處(如初始化方法)添加如下代碼以完成EventBus的注冊(cè)。
EventBus.getDefault().register(this);
然后在適當(dāng)?shù)牡胤教砑尤缦麓a以完成EventBus的注冊(cè)解除,防止泄露。
EventBus.getDefault().unregister(this);
無(wú)論是注冊(cè)或者解除注冊(cè),無(wú)一例外,都是通過(guò)EventBus.getDefault()獲取到的EventBus實(shí)例來(lái)完成的。那么getDefault()方法做了什么操作呢?我們跟進(jìn)代碼看看。
public static EventBus getDefault() {
EventBus instance = defaultInstance;
if (instance == null) {
synchronized (EventBus.class) {
instance = EventBus.defaultInstance;
if (instance == null) {
instance = EventBus.defaultInstance = new EventBus();
}
}
}
return instance;
}
getDefault()方法其實(shí)很簡(jiǎn)單,就是使用單例模式,獲取到了唯一的EventBus對(duì)象。初次使用時(shí),instance對(duì)象勢(shì)必為null,此時(shí)就會(huì)通過(guò)EventBus的無(wú)參構(gòu)造函數(shù)創(chuàng)建出一個(gè)EventBus實(shí)例對(duì)象。無(wú)參構(gòu)造函數(shù)的實(shí)現(xiàn)如下:
public EventBus() {
this(DEFAULT_BUILDER);
}
可以看到,EventBus的無(wú)參構(gòu)造函數(shù),最終調(diào)用的還是帶有單個(gè)參數(shù)的構(gòu)造函數(shù),其參數(shù)類(lèi)型是EventBusBuilder,望文生義,EventBusBuilder明顯是采用建造者模式實(shí)現(xiàn)的,這部分我們后面再分析。無(wú)參構(gòu)造函數(shù)調(diào)用了有參構(gòu)造函數(shù),并傳入了DEFAULT_BUILDER實(shí)參。那么,DEFAULT_BUILDER又是怎樣的呢?其實(shí)它就是一個(gè)EventBusBuilder對(duì)象,只有預(yù)設(shè)定的默認(rèn)配置。
private static final EventBusBuilder DEFAULT_BUILDER = new EventBusBuilder();
DEFAULT_BUILDER傳入到有參的EventBus構(gòu)造函數(shù)后,會(huì)執(zhí)行一些初始化的工作,如下:
EventBus(EventBusBuilder builder) {
logger = builder.getLogger();
subscriptionsByEventType = new HashMap<>();
typesBySubscriber = new HashMap<>();
stickyEvents = new ConcurrentHashMap<>();
mainThreadSupport = builder.getMainThreadSupport();
mainThreadPoster = mainThreadSupport != null ? mainThreadSupport.createPoster(this) : null;
backgroundPoster = new BackgroundPoster(this);
asyncPoster = new AsyncPoster(this);
indexCount = builder.subscriberInfoIndexes != null ? builder.subscriberInfoIndexes.size() : 0;
subscriberMethodFinder = new SubscriberMethodFinder(builder.subscriberInfoIndexes,
builder.strictMethodVerification, builder.ignoreGeneratedIndex);
logSubscriberExceptions = builder.logSubscriberExceptions;
logNoSubscriberMessages = builder.logNoSubscriberMessages;
sendSubscriberExceptionEvent = builder.sendSubscriberExceptionEvent;
sendNoSubscriberEvent = builder.sendNoSubscriberEvent;
throwSubscriberException = builder.throwSubscriberException;
eventInheritance = builder.eventInheritance;
executorService = builder.executorService;
}
在這里,會(huì)取出EventBusBuilder的各項(xiàng)配置值,賦值給相應(yīng)的EventBus中的成員。這是很典型的建造者模式,一般當(dāng)有多項(xiàng)配置時(shí),我們會(huì)考慮采用這種模式。
經(jīng)歷以上流程之后,默認(rèn)的EventBus實(shí)例就通過(guò)getDefault方法獲取到了,并且這個(gè)EventBus是全局唯一的。
代碼分析到這里,我們大概可以知道了,EventBus實(shí)例化可以有兩種方式:
- 使用默認(rèn)的配置,即getDefault()方式
- 使用EventBusBuilder自定義配置,之后通過(guò)build生成
二、默認(rèn)配置
EventBusBuilder是EventBus的建造者,負(fù)責(zé)初始化EventBus的各項(xiàng)配置,并生成EventBus對(duì)象。通過(guò)第一節(jié)的分析,我們會(huì)有一個(gè)疑問(wèn):EventBus的默認(rèn)配置到底是怎么樣的呢?這個(gè)問(wèn)題其實(shí)可以換個(gè)問(wèn)法:EventBusBuilder的默認(rèn)配置到底是怎么樣的呢?讓我們趕緊追進(jìn)代碼分析吧。
public class EventBusBuilder {
private final static ExecutorService DEFAULT_EXECUTOR_SERVICE = Executors.newCachedThreadPool();
boolean logSubscriberExceptions = true;
boolean logNoSubscriberMessages = true;
boolean sendSubscriberExceptionEvent = true;
boolean sendNoSubscriberEvent = true;
boolean throwSubscriberException;
boolean eventInheritance = true;
boolean ignoreGeneratedIndex;
boolean strictMethodVerification;
ExecutorService executorService = DEFAULT_EXECUTOR_SERVICE;
List<Class<?>> skipMethodVerificationForClasses;
List<SubscriberInfoIndex> subscriberInfoIndexes;
Logger logger;
MainThreadSupport mainThreadSupport;
...
}
分析以上EventBusBuilder的成員及賦值,可以得出如下信息:
logSubscriberExceptions :是否打印訂閱者異常信息,默認(rèn)開(kāi)啟
logNoSubscriberMessages :某個(gè)事件沒(méi)有訂閱者時(shí),是否打印信息,默認(rèn)開(kāi)啟
sendSubscriberExceptionEvent :出現(xiàn)訂閱者異常時(shí),是否發(fā)送異常事件,默認(rèn)開(kāi)啟
sendNoSubscriberEvent :某個(gè)事件沒(méi)有訂閱者時(shí),是否發(fā)送無(wú)訂閱者的事件,默認(rèn)開(kāi)啟
throwSubscriberException :是否拋出訂閱者異常信息,默認(rèn)關(guān)閉
eventInheritance :事件是否可以繼承形式訂閱,默認(rèn)開(kāi)啟
ignoreGeneratedIndex :忽略索引生成,默認(rèn)關(guān)閉
strictMethodVerification :是否開(kāi)啟方法嚴(yán)格驗(yàn)證,默認(rèn)關(guān)閉
executorService :線程池,默認(rèn)是newCachedThreadPool,即沒(méi)有核心線程、但最大線程數(shù)是Integer.MAX_VALUE的線程池
skipMethodVerificationForClasses :跳過(guò)為訂閱者類(lèi)里面的方法進(jìn)行校驗(yàn),校驗(yàn)包括注解信息、修飾符是否是public且非static\final的,默認(rèn)為空
subscriberInfoIndexes :訂閱者信息索引,由注解處理器生成
mainThreadSupport :專(zhuān)為Android的主線程定制,持有主線程looper引用
結(jié)合第一節(jié)的分析,到這里我們可以得出結(jié)論,EventBus的默認(rèn)配置是:
- 當(dāng)出現(xiàn)訂閱者異常時(shí),打印異常log
- 當(dāng)事件沒(méi)有訂閱者時(shí),打印沒(méi)有訂閱者log
- 當(dāng)出現(xiàn)訂閱者異常時(shí),發(fā)送異常事件
- 當(dāng)事件沒(méi)有訂閱者時(shí),發(fā)送無(wú)訂閱者事件
- 捕獲異常信息,防止崩潰
- 事件可以繼承
- 編譯時(shí)生成索引
- 采用最大限制是Integer.MAX_VALUE的緩存線程池
- 為每個(gè)訂閱者類(lèi)都進(jìn)行方法校驗(yàn)
- 當(dāng)處于Android平臺(tái)時(shí),確??梢郧袚Q到主線程
三、自定義配置
那么如何進(jìn)行自定義的EventBus配置呢?聰明的你一定想到了。是的,我們可以通過(guò)EventBusBuilder來(lái)實(shí)現(xiàn)自定義配置。EventBusBuilder內(nèi)部提供了一系列的配置方法,方便用戶采用鏈?zhǔn)秸{(diào)用的方式,來(lái)生成一個(gè)EventBusBuilder對(duì)象。然而,通過(guò)查看EventBus源碼可知,EventBusBuilder的構(gòu)造方法的修飾符是protected的,也就是說(shuō),用戶無(wú)法通過(guò)直接new的方式來(lái)創(chuàng)建EventBusBuilder對(duì)象。這樣不就無(wú)法自定義配置了嗎?別急,雖然我們無(wú)法直接new出一個(gè)EventBusBuilder對(duì)象,但是EventBus類(lèi)提供了一個(gè)靜態(tài)方法builder(),該方法內(nèi)部默認(rèn)new了一個(gè)EventBusBuilder對(duì)象,如下:
public static EventBusBuilder builder() {
return new EventBusBuilder();
}
通過(guò)builder()方法,用戶就可以獲取到EventBusBuilder對(duì)象,之后就可以隨心所欲地自定義配置了。配置有如下兩種使用姿勢(shì):
姿勢(shì)1:
EventBus.builder().logNoSubscriberMessages(false)
.logSubscriberExceptions(false).eventInheritance(false)...
.installDefaultEventBus();
姿勢(shì)2:
EventBus.builder().logNoSubscriberMessages(false)
.logSubscriberExceptions(false).eventInheritance(false)...
.build();
上述兩種姿勢(shì)看起來(lái)非常相似,但其實(shí)是有區(qū)別的,區(qū)別就在于創(chuàng)建EventBus實(shí)例的方式,姿勢(shì)1使用的是installDefaultEventBus方法,姿勢(shì)2使用的是build方法。我們來(lái)看看這兩種方法的內(nèi)部實(shí)現(xiàn)。
public EventBus installDefaultEventBus() {
synchronized (EventBus.class) {
if (EventBus.defaultInstance != null) {
throw new EventBusException("Default instance already exists." +
" It may be only set once before it's used the first time to ensure consistent behavior.");
}
EventBus.defaultInstance = build();
return EventBus.defaultInstance;
}
}
public EventBus build() {
return new EventBus(this);
}
看出區(qū)別了嗎?installDefaultEventBus方法在內(nèi)部其實(shí)也是調(diào)用的build方法,但不同的是,installDefaultEventBus可以確保EventBus實(shí)例的全局唯一性,當(dāng)defaultInstance非空時(shí),會(huì)直接拋出異常。而姿勢(shì)2直接使用build方法創(chuàng)建EventBus實(shí)例的方式,則需要用戶自身確保EventBus實(shí)例的全局唯一性。
EventBus并非一定要全局唯一,但確保全局唯一,不是可以更好更合理地管理和分發(fā)事件嗎?
四、結(jié)束語(yǔ)
通過(guò)以上幾小節(jié)的分析,我們已經(jīng)知道了EventBus的默認(rèn)配置情況,以及如何自定義配置。但如果再仔細(xì)觀察,會(huì)發(fā)現(xiàn),在 EventBus(EventBusBuilder builder) 構(gòu)造函數(shù)中,還默認(rèn)實(shí)例化了幾個(gè)成員對(duì)象:
subscriptionsByEventType = new HashMap<>();
typesBySubscriber = new HashMap<>();
stickyEvents = new ConcurrentHashMap<>();
mainThreadPoster = mainThreadSupport != null ? mainThreadSupport.createPoster(this) : null;
backgroundPoster = new BackgroundPoster(this);
asyncPoster = new AsyncPoster(this);
subscriberMethodFinder = new SubscriberMethodFinder(builder.subscriberInfoIndexes,
builder.strictMethodVerification, builder.ignoreGeneratedIndex);
這些成員是用來(lái)做什么的呢?我們先留個(gè)懸念,在后面的幾章中進(jìn)行詳細(xì)的分析。