前言
說起Eventbus,相信不少同學(xué)都已經(jīng)使用過晕窑。之前一直聽別人提起,但是我一直沒有使用過幕屹。前段時間在做一個IMdemo的時候用上了,原來模塊間的通信可以這么方便望拖,遂勾起了我的興趣,決定好好研究一番说敏。那么它的用法和好處我就不介紹了,直接進(jìn)入主題盔沫。
正題
本篇文章解析EventBus注冊的源碼。
可以看到EventBus使用的單例模式創(chuàng)建的實例架诞,但是EventBus的構(gòu)造函數(shù)卻不是私有的(這樣就可以自己new個EventBus對象)干茉,讓我們看看源碼谴忧。
public static EventBus getDefault() {
if (defaultInstance == null) {
synchronized (EventBus.class) {
if (defaultInstance == null) {
defaultInstance = new EventBus();
}
}
}
return defaultInstance;
}
/**
* Creates a new EventBus instance; each instance is a separate scope in which events are delivered. To use a
* central bus, consider {@link #getDefault()}.
*/
public EventBus() {
this(DEFAULT_BUILDER);
}
EventBus(EventBusBuilder builder) {
subscriptionsByEventType = new HashMap<>();
typesBySubscriber = new HashMap<>();
stickyEvents = new ConcurrentHashMap<>();
mainThreadPoster = new HandlerPoster(this, Looper.getMainLooper(), 10);
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;
}
原來因為是要初始化一些成員變量,如果把構(gòu)造器設(shè)為私有那么就不能在構(gòu)造函數(shù)中初始化這些成員變量委造。而且源碼的注釋寫的很清楚實例化EventBus使用getDefault()方法。
有些時候我們想要自己去配置一個EventBusBuilder昏兆,但是源碼中沒有提供可以把EventBusBuilder作為參數(shù)傳遞給EventBus然后創(chuàng)建EventBus實例的方法。那么如何創(chuàng)建一個我們自己定義的EventBusBuilder實例呢妇穴?這時候需要使用另一種創(chuàng)建EventBus實例的方法了爬虱。源碼給我們提供了一個得到EventBusBuilder的方法
public static EventBusBuilder builder() {
return new EventBusBuilder();
}
為什么給我們提供這個方法伟骨,我們不可以直接new一個出來嗎燃异?
原來EventBusBuilder的構(gòu)造函數(shù)不是public的。回俐。。仅颇。但是EventBusBuilder有個方法可以得到EventBus實例
/**
* Installs the default EventBus returned by {@link EventBus#getDefault()} using this builders' values. Must be
* done only once before the first usage of the default EventBus.
*
* @throws EventBusException if there's already a default EventBus instance in place
*/
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;
}
}
下面放上創(chuàng)建自己配制EventBusBuilder的EventBus實例完整代碼
EventBus e = EventBus.builder()
.eventInheritance(true)
.ignoreGeneratedIndex(true)
.installDefaultEventBus();
接著往下走,得到了EventBus的時候后就要register忘瓦。
/**
* Registers the given subscriber to receive events. Subscribers must call {@link #unregister(Object)} once they
* are no longer interested in receiving events.
* <p/>
* Subscribers have event handling methods that must be annotated by {@link Subscribe}.
* The {@link Subscribe} annotation also allows configuration like {@link
* ThreadMode} and priority.
*/
public void register(Object subscriber) {
//得到訂閱者的運行時類Class對象
Class<?> subscriberClass = subscriber.getClass();
//訂閱者中被包裝成SubscriberMethod對象的接收方法的集合
List<SubscriberMethod> subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass);
synchronized (this) {
for (SubscriberMethod subscriberMethod : subscriberMethods) {
subscribe(subscriber, subscriberMethod);
}
}
}
源碼的注釋是注冊訂閱者接收時間,不再使用的時候通過unregister(Object)方法取消注冊耕皮。注冊者必須含有一個處理事件并含有Subscribe注解的方法,注釋中允許配置ThreadMode等屬性凌停。
通過subscriberMethodFinder.findSubscriberMethods(subscriberClass)這個方法找到訂閱中接收事件的方法并包裝成SubscriberMethod對象,點進(jìn)去看一下
List<SubscriberMethod> findSubscriberMethods(Class<?> subscriberClass) {
//在緩存中查找是否含有SubscriberMethod集合
List<SubscriberMethod> subscriberMethods = METHOD_CACHE.get(subscriberClass);
if (subscriberMethods != null) {
return subscriberMethods;
}
//ignoreGeneratedIndex默認(rèn)為為false
if (ignoreGeneratedIndex) {
subscriberMethods = findUsingReflection(subscriberClass);
} else {
subscriberMethods = findUsingInfo(subscriberClass);
}
if (subscriberMethods.isEmpty()) {
throw new EventBusException("Subscriber " + subscriberClass
+ " and its super classes have no public methods with the @Subscribe annotation");
} else {
METHOD_CACHE.put(subscriberClass, subscriberMethods);
return subscriberMethods;
}
}
首先通過緩存找到是否SubscriberMethod對象台诗,我們第一次注冊該訂閱者,所有緩存中是沒有的拉队。接著判斷ignoreGeneratedIndex(是否忽略生成的索引),這個可以在EventBusBuildr中去設(shè)置粱快,默認(rèn)為false。所以執(zhí)行 subscriberMethods = findUsingInfo(subscriberClass)
private List<SubscriberMethod> findUsingInfo(Class<?> subscriberClass) {
FindState findState = prepareFindState();
findState.initForSubscriber(subscriberClass);
while (findState.clazz != null) {
findState.subscriberInfo = getSubscriberInfo(findState);
if (findState.subscriberInfo != null) {
SubscriberMethod[] array = findState.subscriberInfo.getSubscriberMethods();
for (SubscriberMethod subscriberMethod : array) {
if (findState.checkAdd(subscriberMethod.method, subscriberMethod.eventType)) {
findState.subscriberMethods.add(subscriberMethod);
}
}
} else {
findUsingReflectionInSingleClass(findState);
}
findState.moveToSuperclass();
}
return getMethodsAndRelease(findState);
}
private FindState prepareFindState() {
//private static final int POOL_SIZE = 4;
// private static final FindState[] FIND_STATE_POOL = new FindState[POOL_SIZE];
synchronized (FIND_STATE_POOL) {
for (int i = 0; i < POOL_SIZE; i++) {
FindState state = FIND_STATE_POOL[i];
if (state != null) {
FIND_STATE_POOL[i] = null;
return state;
}
}
}
return new FindState();
}
private SubscriberInfo getSubscriberInfo(FindState findState) {
if (findState.subscriberInfo != null && findState.subscriberInfo.getSuperSubscriberInfo() != null) {
SubscriberInfo superclassInfo = findState.subscriberInfo.getSuperSubscriberInfo();
if (findState.clazz == superclassInfo.getSubscriberClass()) {
return superclassInfo;
}
}
if (subscriberInfoIndexes != null) {
for (SubscriberInfoIndex index : subscriberInfoIndexes) {
SubscriberInfo info = index.getSubscriberInfo(findState.clazz);
if (info != null) {
return info;
}
}
}
return null;
}
void initForSubscriber(Class<?> subscriberClass) {
this.subscriberClass = clazz = subscriberClass;
skipSuperClasses = false;
subscriberInfo = null;
}
這里的findState.subscriberInfo為null皆尔,執(zhí)行findUsingReflectionInSingleClass(findState)
private void findUsingReflectionInSingleClass(FindState findState) {
Method[] methods;
try {
// This is faster than getMethods, especially when subscribers are fat classes like Activities
//通過反射獲取訂閱者中的所有方法的所有公用(public)方法包括其繼承類的公用方法,包括它所實現(xiàn)接口的方法慷蠕。
methods = findState.clazz.getDeclaredMethods();
} catch (Throwable th) {
// Workaround for java.lang.NoClassDefFoundError, see https://github.com/greenrobot/EventBus/issues/149
//通過反射獲取訂閱者中類所有方法,包括公共流炕、保護(hù)、默認(rèn)(包)訪問和私有方法每辟,但不包括繼承的方法。包括它所實現(xiàn)接口的方法渠欺。
methods = findState.clazz.getMethods();
//跳過檢查父類
findState.skipSuperClasses = true;
}
//遍歷所有找到的方法
for (Method method : methods) {
//拿到方法中修飾符的類型
int modifiers = method.getModifiers();
//判斷方法中的修飾符是否為public且沒有ABSTRACT、STATIC挠将、BRIDGE、SYNTHETIC等關(guān)鍵字
if ((modifiers & Modifier.PUBLIC) != 0 && (modifiers & MODIFIERS_IGNORE) == 0) {
//以數(shù)組形式拿到方法中的參數(shù)
Class<?>[] parameterTypes = method.getParameterTypes();
//判斷數(shù)組的長度是否為1
if (parameterTypes.length == 1) {
//拿到方法的注解
Subscribe subscribeAnnotation = method.getAnnotation(Subscribe.class);
if (subscribeAnnotation != null) {
//eventType是EventBus的Model類
Class<?> eventType = parameterTypes[0];
if (findState.checkAdd(method, eventType)) {
ThreadMode threadMode = subscribeAnnotation.threadMode();
//把訂閱者中接收事件的方法包裝成一個SubscriberMethod對象
findState.subscriberMethods.add(new SubscriberMethod(method, eventType, threadMode,
subscribeAnnotation.priority(), subscribeAnnotation.sticky()));
}
}
//參數(shù)長度>1時拋出異常
} else if (strictMethodVerification && method.isAnnotationPresent(Subscribe.class)) {
String methodName = method.getDeclaringClass().getName() + "." + method.getName();
throw new EventBusException("@Subscribe method " + methodName +
"must have exactly 1 parameter but has " + parameterTypes.length);
}
//方法中有不正確的關(guān)鍵字拋出異常
} else if (strictMethodVerification && method.isAnnotationPresent(Subscribe.class)) {
String methodName = method.getDeclaringClass().getName() + "." + method.getName();
throw new EventBusException(methodName +
" is a illegal @Subscribe method: must be public, non-static, and non-abstract");
}
}
}
/** 雙重檢查
* 1乳丰。檢查是否已添加在當(dāng)前訂閱者中處理事件的方法
* 2。檢查接收事件的方法的聲明類
*/
boolean checkAdd(Method method, Class<?> eventType) {
// 2 level check: 1st level with event type only (fast), 2nd level with complete signature when required.
// Usually a subscriber doesn't have methods listening to the same event type.
Object existing = anyMethodByEventType.put(eventType, method);
if (existing == null) {
return true;
} else {
if (existing instanceof Method) {
if (!checkAddWithMethodSignature((Method) existing, eventType)) {
// Paranoia check
throw new IllegalStateException();
}
// Put any non-Method object to "consume" the existing Method
anyMethodByEventType.put(eventType, this);
}
return checkAddWithMethodSignature(method, eventType);
}
}
private boolean checkAddWithMethodSignature(Method method, Class<?> eventType) {
methodKeyBuilder.setLength(0);
methodKeyBuilder.append(method.getName());
methodKeyBuilder.append('>').append(eventType.getName());
String methodKey = methodKeyBuilder.toString();
Class<?> methodClass = method.getDeclaringClass();
Class<?> methodClassOld = subscriberClassByMethodKey.put(methodKey, methodClass);
if (methodClassOld == null || methodClassOld.isAssignableFrom(methodClass)) {
// Only add if not already found in a sub class
return true;
} else {
// Revert the put, old class is further down the class hierarchy
subscriberClassByMethodKey.put(methodKey, methodClassOld);
return false;
}
}
這段代碼很長产园,大致就是檢查接收事件的方法是否符合規(guī)范(EventBus通過此規(guī)范找到接收事件的方法)之后添加進(jìn)接收事件方法的集合夜郁,否則拋出異常什燕。并且是通過反射實現(xiàn)的拂酣。接著檢查訂閱者是否還有父類,沒有則跳出循環(huán)
void moveToSuperclass() {
if (skipSuperClasses) {
clazz = null;
} else {
clazz = clazz.getSuperclass();
String clazzName = clazz.getName();
/** Skip system classes, this just degrades performance. */
if (clazzName.startsWith("java.") || clazzName.startsWith("javax.") || clazzName.startsWith("android.")) {
clazz = null;
}
}
}
跳出循環(huán)后婶熬,拿到接收事件方法的集合,并重置findState對象
private List<SubscriberMethod> getMethodsAndRelease(FindState findState) {
List<SubscriberMethod> subscriberMethods = new ArrayList<>(findState.subscriberMethods);
findState.recycle();
synchronized (FIND_STATE_POOL) {
for (int i = 0; i < POOL_SIZE; i++) {
if (FIND_STATE_POOL[i] == null) {
FIND_STATE_POOL[i] = findState;
break;
}
}
}
return subscriberMethods;
}
接著遍歷SubscriberMethod的集合赵颅,訂閱事件
for (SubscriberMethod subscriberMethod : subscriberMethods) {
//subscriber訂閱者。subscriberMethod接收事件的方法
subscribe(subscriber, subscriberMethod);
}
// Must be called in synchronized block
private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) {
//EventBus Model類
Class<?> eventType = subscriberMethod.eventType;
//包裝成訂閱請求
Subscription newSubscription = new Subscription(subscriber, subscriberMethod);
CopyOnWriteArrayList<Subscription> subscriptions = subscriptionsByEventType.get(eventType);
if (subscriptions == null) {
subscriptions = new CopyOnWriteArrayList<>();
subscriptionsByEventType.put(eventType, subscriptions);
} else {
if (subscriptions.contains(newSubscription)) {
throw new EventBusException("Subscriber " + subscriber.getClass() + " already registered to event "
+ eventType);
}
}
int size = subscriptions.size();
//訂閱優(yōu)先級
for (int i = 0; i <= size; i++) {
if (i == size || subscriberMethod.priority > subscriptions.get(i).subscriberMethod.priority) {
subscriptions.add(i, newSubscription);
break;
}
}
List<Class<?>> subscribedEvents = typesBySubscriber.get(subscriber);
//將事件訂閱捂刺,之后post會從typesBySubscriber中獲取訂閱者并發(fā)送事件
if (subscribedEvents == null) {
subscribedEvents = new ArrayList<>();
typesBySubscriber.put(subscriber, subscribedEvents);
}
subscribedEvents.add(eventType);
//判斷是否為粘性事件
if (subscriberMethod.sticky) {
if (eventInheritance) {
// Existing sticky events of all subclasses of eventType have to be considered.
// Note: Iterating over all events may be inefficient with lots of sticky events,
// thus data structure should be changed to allow a more efficient lookup
// (e.g. an additional map storing sub classes of super classes: Class -> List<Class>).
Set<Map.Entry<Class<?>, Object>> entries = stickyEvents.entrySet();
for (Map.Entry<Class<?>, Object> entry : entries) {
Class<?> candidateEventType = entry.getKey();
if (eventType.isAssignableFrom(candidateEventType)) {
Object stickyEvent = entry.getValue();
checkPostStickyEventToSubscription(newSubscription, stickyEvent);
}
}
} else {
Object stickyEvent = stickyEvents.get(eventType);
checkPostStickyEventToSubscription(newSubscription, stickyEvent);
}
}
}
以上就是訂閱事件的處理了,遍歷subscriberMethods集合族展,把每個subscriberMethods再次包裝成訂閱請求并添加進(jìn)typesBySubscriber(hashmap)中,之后post或就會從中取出請求并給訂閱者發(fā)送消息仪缸。
歸根到底Event使用觀察者模式+反射完成它的運作