- 寫在前面:如果你看到這篇文章,希望你能夠自己對(duì)照著源碼走一遍,直接反射或者使用索引都會(huì)詳細(xì)分析使用的!
EventBus優(yōu)點(diǎn)和特性
- 也許你有個(gè)疑問: 市面上有很多事件傳遞框架為何選擇EventBus,而不是Otto , Rxbus等,相比較他們都可以滿足日常開發(fā)需求,只是后兩者更新基本停滯,而EventBus還在正常更新維護(hù),選擇接入人數(shù)也是最多的,同時(shí)功能也是最全的,如果你選擇了使用該框架,自然了解源碼的運(yùn)行對(duì)于調(diào)試絕對(duì)是有幫助的!
- 我們學(xué)知識(shí)不能簡簡單單只是會(huì)用而已,要知其然而知其所以然才能進(jìn)步,提升自己~
優(yōu)點(diǎn)
- 簡化組件間的通信,解耦事件發(fā)送和接受者
- 很好的應(yīng)用于Activity,Fragment之間,后臺(tái)線程之間的通信,避免使用多個(gè)Intent傳遞,handler通信等
- 避免復(fù)雜的,易于出錯(cuò)的依賴和生命周期問題,比如多個(gè)Activity跳轉(zhuǎn)后的回調(diào)問題
- 速度響應(yīng)快,尤其是3.0以后再編譯器增加索引
- 輕量大概50K左右的jar包
- 被大量的app所使用,在實(shí)際中被驗(yàn)證
- 有很多的高級(jí)功能,如線程切換模式,訂閱的優(yōu)先級(jí)等
特性
- 簡單易用的注解API : 簡單的@Subscribe注解放到訂閱方法上即可通過編譯期的訂閱者索引,app就可以不用在運(yùn)行期通過注解反射拿到訂閱了
- 支持事件投遞到UI線程,不管事件是從哪個(gè)線程發(fā)送過來的
- 支持事件和訂閱者的繼承關(guān)系: 如 事件A是事件B的父類,則發(fā)送B類型的事件,該事件也會(huì)發(fā)送給對(duì)于事件A感興趣的訂閱者,對(duì)于訂閱者也存在相似的繼承關(guān)系,可以通過eventInheritance(false)關(guān)閉該功能,只在本類中調(diào)用,父類接口不在回調(diào)的
- 即可零設(shè)定EventBus直接工作,也可以通過構(gòu)建者模式調(diào)整EventBus的行為,滿足你的需求EventBusBuilder.builder()
//通過EventBusBuilder.builder()的方法構(gòu)建EventBusBuilder對(duì)象配置里面的信息以后調(diào)用build()方法創(chuàng)建
public EventBus build() { //創(chuàng)建一個(gè)EventBus對(duì)象
return new EventBus(this);
}
復(fù)制代碼
- 注意:通過此方法可以創(chuàng)建多個(gè)EventBus對(duì)象,且每個(gè)配置信息不同,但是每個(gè)EventBus的實(shí)例都是獨(dú)立的,也就是說每個(gè)EventBus post事件,只要使用該EventBus注冊(cè)的訂閱者才能接收到,其他EventBus注冊(cè)的是無法接收的即在EventBus.getEventBus(type).regirst(this)的Activity或者Fragment中的方法都注冊(cè)到了該type返回的EventBus中啦!
EventBus的構(gòu)建
- 首先分析該類的各個(gè)屬性含義
private final static ExecutorService DEFAULT_EXECUTOR_SERVICE = Executors.newCachedThreadPool();
ExecutorService executorService = DEFAULT_EXECUTOR_SERVICE;
//默認(rèn)線程池,是一個(gè)核心0,最大Max,無緩存隊(duì)列SynchronousQueue;如果大量事件一起發(fā)送可能導(dǎo)致OOM,一般需要更改一下線程池配置
//通過build的方法executorService(executorService)傳遞進(jìn)來,主要用于異步和后臺(tái)事件傳遞
////在訂閱方法中拋出異常時(shí),是否打印日志,在類中注解重寫onSubscriberExceptionEvent可以監(jiān)聽到
boolean logSubscriberExceptions = true;
//沒有找到訂閱方法,是否打印日志
boolean logNoSubscriberMessages = true;
//在非訂閱SubscriberExceptionEvent事件方法中拋出異常時(shí), 是否發(fā)送SubscriberExceptionEvent事件
boolean sendSubscriberExceptionEvent = true;
//沒找到事件訂閱方法,是否發(fā)送NoSubscriberEvent事件
boolean sendNoSubscriberEvent = true;
//在非訂閱SubscriberExceptionEvent事件方法中拋出異常時(shí), 是否拋出EventBusException異常, 默認(rèn)為false
boolean throwSubscriberException;
boolean eventInheritance = true; //發(fā)送子事件,是否發(fā)送父事件,默認(rèn)為true,最好改成false,避免不必要的麻煩
//三個(gè)參數(shù)用于參照訂閱方法
boolean ignoreGeneratedIndex; //是否直接用反射查找訂閱方法(就是運(yùn)行期查找,速度慢耗時(shí),3.0以后優(yōu)化使用索引的),默認(rèn)是false
boolean strictMethodVerification; //非注解生成索引時(shí),嚴(yán)格方法驗(yàn)證:當(dāng)方法不符合格式(public,非abstract, 非static,非橋接方法,只有一個(gè)參數(shù))時(shí),是否拋出EventBusException異常,默認(rèn)false
List<SubscriberInfoIndex> subscriberInfoIndexes; //注解生成的索引,在編譯器生成,需要通過android-apt三方插件或annotationProcessor生成
List<Class<?>> skipMethodVerificationForClasses; //檢查以onEvent開頭的方法,基本不用啦,都是使用注解自定義方法了
復(fù)制代碼
-
注意: 對(duì)EventBus增加索引,必須在第一個(gè)EventBus.regirst之前,因此一般操作都是在Application的oncreate方法中添加
//提高性能:第一點(diǎn)是關(guān)閉父類以及接口查找分發(fā)事件(只有本類調(diào)取,父類接口不在回調(diào))樊卓; //第二點(diǎn) 添加索引拿愧,索引添加的原理就是提前在編譯的時(shí)候加載好注冊(cè)類的相關(guān)信息。 EventBus.builder().addIndex(new MyEventBusIndex()).eventInheritance(false).installDefaultEventBus(); //EventBus.getDefault() 獲得的即為當(dāng)前installDefaultEventBus方法生成的,不會(huì)在重新創(chuàng)建了,但是如果通過builder.build()重新構(gòu)建的EventBus就無效了! 復(fù)制代碼
這里我們主要通過Event3.0的源碼,畢竟用新不用舊嘛
注解Subscribe
- 通過注解標(biāo)記訂閱方法:同時(shí)可以指定threadMode,代表該訂閱方法運(yùn)行的線程,指定sticky,代表是否是粘性事件,指定priority代表優(yōu)先級(jí)(由高到底依次接收,可以更改設(shè)置)
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface Subscribe {
ThreadMode threadMode() default ThreadMode.POSTING;
boolean sticky() default false;
int priority() default 0;
}
復(fù)制代碼
- threadMode: 訂閱方法運(yùn)行的線程
- ThreadMode.POSTING —— POST線程碌尔,訂閱方法運(yùn)行在發(fā)布者所在的線程(默認(rèn))
- ThreadMode.MAIN —— UI主線程浇辜,訂閱方法運(yùn)行在主線程,發(fā)送如果是UI線程直接運(yùn)行,如果不是通過Handler回調(diào)到UI線程運(yùn)行
- ThreadMode.BACKGROUND —— 后臺(tái)線程,發(fā)布者是主線程唾戚,訂閱方法運(yùn)行在新開子線程柳洋;發(fā)布者是子線程,訂閱方法運(yùn)行在發(fā)布者所在的線程叹坦;(通過線程池創(chuàng)建子線程)
- ThreadMode.ASYNC —— 異步線程熊镣,訂閱方法運(yùn)行在新開子線程,無論發(fā)布者是在哪個(gè)線程(同上共用一個(gè)線程池)
- sticky: 與Android廣播中的sticky概念一致,表示如果當(dāng)前還未注冊(cè),則通過postSticky發(fā)送的廣播將會(huì)保存在內(nèi)存中,當(dāng)有注冊(cè)時(shí)就會(huì)法將該粘性事件傳遞給訂閱者,即先發(fā)送后訂閱是可以接收到的!
- priority:訂閱優(yōu)先級(jí),事件發(fā)送以后根據(jù)優(yōu)先級(jí)傳遞,相同優(yōu)先級(jí)根據(jù)訂閱順序傳遞(添加由大->小,調(diào)取方法直接輪詢由0 -> size從而達(dá)到事件傳遞性,且事件對(duì)象不可變但屬性值可變從而可以更改值的傳遞)
注冊(cè)register
- EventBus通過register注冊(cè)到Activity或Fragment中
public void register(Object subscriber) { //subscriber表示this
Class<?> subscriberClass = subscriber.getClass(); //獲取this代表的類
List<SubscriberMethod> subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass); //查找訂閱者類中的所有訂閱方法
synchronized (this) {
for (SubscriberMethod subscriberMethod : subscriberMethods) {
subscribe(subscriber, subscriberMethod);
}
}
}
//SubscriberMethod類的屬性
public class SubscriberMethod {
final Method method; //訂閱方法
final ThreadMode threadMode; //訂閱方法在哪個(gè)線程執(zhí)行
final Class<?> eventType; //事件類
final int priority; //優(yōu)先級(jí)
final boolean sticky; //是否是粘性
/** Used for efficient comparison */
String methodString;
復(fù)制代碼
- 看一下 subscriberMethodFinder.findSubscriberMethods如何查找訂閱方法
//首先肯定是subscriberMethodFinder的創(chuàng)建:在EventBus的構(gòu)造函數(shù)
subscriberMethodFinder = new SubscriberMethodFinder(builder.subscriberInfoIndexes,
builder.strictMethodVerification, builder.ignoreGeneratedIndex); //注意里面?zhèn)鬟f的參數(shù): 索引,方法驗(yàn)證是否符合,是否使用反射調(diào)用
//引入EventBus的第一個(gè)緩存map集合: 鍵表示當(dāng)前注冊(cè)類activity或者Fragment,值表示當(dāng)前類中的訂閱方法的集合
private static final Map<Class<?>, List<SubscriberMethod>> METHOD_CACHE = new ConcurrentHashMap<>();
List<SubscriberMethod> findSubscriberMethods(Class<?> subscriberClass) {
List<SubscriberMethod> subscriberMethods = METHOD_CACHE.get(subscriberClass);
if (subscriberMethods != null) { //如果注冊(cè)類已經(jīng)緩存過了,直接返回
return subscriberMethods;
}
//ignoreGeneratedIndex表示使用反射也就是忽略注解器編譯器生成的MyEventBusIndex類,默認(rèn)是false
if (ignoreGeneratedIndex) {
subscriberMethods = findUsingReflection(subscriberClass); //通過反射調(diào)用,在運(yùn)行期
} else { //我們都會(huì)添加編譯器生成的代碼邏輯
subscriberMethods = findUsingInfo(subscriberClass);//// 從注解器生成的MyEventBusIndex類中獲得訂閱類的訂閱方法信息
}
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); //調(diào)用完成以后添加到緩存中
return subscriberMethods;
}
}
復(fù)制代碼
- 首先我們先看通過反射來獲取訂閱類中的訂閱方法信息findUsingReflection,通過索引獲取的稍后解釋
private List<SubscriberMethod> findUsingReflection(Class<?> subscriberClass) {
FindState findState = prepareFindState();
findState.initForSubscriber(subscriberClass);//從數(shù)組長度為4中取值并初始化Findstate
while (findState.clazz != null) {
findUsingReflectionInSingleClass(findState); //找到類中的所有事件響應(yīng)方法
findState.moveToSuperclass(); //繼續(xù)尋找當(dāng)前類父類中注冊(cè)的事件響應(yīng)方法
}
return getMethodsAndRelease(findState);
}
復(fù)制代碼
- 查找類中的所有事件響應(yīng)方法
private void findUsingReflectionInSingleClass(FindState findState) {
Method[] methods;
try {
// 獲取類中的所有方法,包括私有方法
methods = findState.clazz.getDeclaredMethods();
} catch (Throwable th) {
// Workaround for java.lang.NoClassDefFoundError, see https://github.com/greenrobot/EventBus/issues/149
methods = findState.clazz.getMethods();
findState.skipSuperClasses = true;
}
for (Method method : methods) {
int modifiers = method.getModifiers(); //獲取方法的屬性,private,static等
if ((modifiers & Modifier.PUBLIC) != 0 && (modifiers & MODIFIERS_IGNORE) == 0) { //如果方法時(shí)public,且不是abstract,static,bridge, synthetic編譯器生成的
Class<?>[] parameterTypes = method.getParameterTypes();//獲取方法參數(shù),且參數(shù)只有1個(gè)
if (parameterTypes.length == 1) {
Subscribe subscribeAnnotation = method.getAnnotation(Subscribe.class); //獲取以Subscribe注解的方法
if (subscribeAnnotation != null) {
Class<?> eventType = parameterTypes[0]; //獲取事件類
if (findState.checkAdd(method, eventType)) {
ThreadMode threadMode = subscribeAnnotation.threadMode();
findState.subscriberMethods.add(new SubscriberMethod(method, eventType, threadMode,
subscribeAnnotation.priority(), subscribeAnnotation.sticky())); //將一個(gè)類中的所有訂閱方法都加入到findstate的集合中
}
}
} 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);
}
} 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");
}
}
}
復(fù)制代碼
- 我們看一下FindState類的屬性
//FindState是SubscriberMethodFinder的靜態(tài)內(nèi)部類,類不長,我們都拿過來吧
static class FindState {
final List<SubscriberMethod> subscriberMethods = new ArrayList<>(); //訂閱方法信息列表
final Map<Class, Object> anyMethodByEventType = new HashMap<>(); //以事件類型為key,方法信息為value的集合
final Map<String, Class> subscriberClassByMethodKey = new HashMap<>(); //以methodkey為key,訂閱者類為value集合 (下方的methodkey : method方法所在的類)
final StringBuilder methodKeyBuilder = new StringBuilder(128); //生成methodkey
//methodkey 是由method名字,事件類名稱組成
Class<?> subscriberClass; //訂閱者類
Class<?> clazz;
boolean skipSuperClasses; //是否跳過父類
SubscriberInfo subscriberInfo;
void initForSubscriber(Class<?> subscriberClass) { //初始化
this.subscriberClass = clazz = subscriberClass;
skipSuperClasses = false;
subscriberInfo = null;
}
void recycle() {
subscriberMethods.clear();
anyMethodByEventType.clear();
subscriberClassByMethodKey.clear();
methodKeyBuilder.setLength(0);
subscriberClass = null;
clazz = null;
skipSuperClasses = false;
subscriberInfo = null;
}
//檢查訂閱者中注冊(cè)的事件響應(yīng)是否可以合法的加入到訂閱方法信息中,分為兩層檢查
boolean checkAdd(Method method, Class<?> eventType) { //method是訂閱方法,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 {
//如果當(dāng)前事件類型在同一個(gè)類中對(duì)應(yīng)多個(gè)方法,則檢查他們方法簽名是否一致
if (existing instanceof Method) { //existing是相同的鍵對(duì)應(yīng)的oldValue
if (!checkAddWithMethodSignature((Method) existing, eventType)) {
// Paranoia check
throw new IllegalStateException();
}
// Put any non-Method object to "consume" the existing Method
anyMethodByEventType.put(eventType, this); //方法簽名不一致(一個(gè)類中多個(gè)方法中含有同一個(gè)事件類)添加FindState作為value
}
return checkAddWithMethodSignature(method, eventType);
}
}
//使用訂閱方法簽名檢測是否可以加入訂閱方法信息列表中,method訂閱方法,eventType事件類
private boolean checkAddWithMethodSignature(Method method, Class<?> eventType) {
methodKeyBuilder.setLength(0);
methodKeyBuilder.append(method.getName());
methodKeyBuilder.append('>').append(eventType.getName());
//方法簽名methodkey怎么生成的
String methodKey = methodKeyBuilder.toString();
Class<?> methodClass = method.getDeclaringClass(); //方法所在的類
Class<?> methodClassOld = subscriberClassByMethodKey.put(methodKey, methodClass);
if (methodClassOld == null || methodClassOld.isAssignableFrom(methodClass)) //methodClass是MethodClassOld的子類或者子接口
{
//如果不存在同樣方法簽名的訂閱方法或 之前保存的訂閱方法所在的類為當(dāng)前將要添加的訂閱方法所在的類的子類(目前不存在此情況募书,因?yàn)橹粫?huì)從子類向父類查找)绪囱,則可以合法添加此訂閱方法信息
return true;
} else {
// 存在同樣方法簽名,且methodOld是子類
//subscriberClassByMethodKey只保存父子繼承關(guān)系的最下層子類,目的是為了在子類注冊(cè)監(jiān)聽事件時(shí)莹捡,如果父類中有相同的事件響應(yīng)方法鬼吵,應(yīng)該調(diào)用子類的覆寫方法
subscriberClassByMethodKey.put(methodKey, methodClassOld);
return false;
}
}
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;
}
}
}
}
復(fù)制代碼
- 以上對(duì)于FindState中的步驟為:
- 通過反射獲取class的所有方法
- 過濾掉不是public和是abstract,static,bridge,synthetic的方法,且參數(shù)只有一個(gè)的
- 找出別subScribe注解修飾的方法
- 將method和事件類型添加到findState中
- 將所有的method訂閱方法封裝成SubscribeMethod添加到findState中集合類中
- 這就是查詢訂閱方法的步驟,下面接著上文,繼續(xù)注冊(cè)步驟!
- 我們目光從新回到注冊(cè)邏輯上面來
public void register(Object subscriber) {
Class<?> subscriberClass = subscriber.getClass();
List<SubscriberMethod> subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass); //上面已經(jīng)具體分析了,如何去找到該類中的所有訂閱方法
synchronized (this) {
for (SubscriberMethod subscriberMethod : subscriberMethods) {
subscribe(subscriber, subscriberMethod); //遍歷方法調(diào)取
}
}
}
復(fù)制代碼
- 我們看subscribe(subscriber, subscriberMethod) 參數(shù): 當(dāng)前訂閱類, 訂閱類中的訂閱方法
// Must be called in synchronized block
private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) {
Class<?> eventType = subscriberMethod.eventType; //訂閱方法的事件類
Subscription newSubscription = new Subscription(subscriber, subscriberMethod); //創(chuàng)建一個(gè)訂閱類的封裝,注意參數(shù)
CopyOnWriteArrayList<Subscription> subscriptions = subscriptionsByEventType.get(eventType); //從緩存中根據(jù)事件類獲取訂閱類的封裝集合
if (subscriptions == null) { //從中查找,如果不存在就添加進(jìn)入,如果存在集合且集合中已經(jīng)添加過了拋出異常,不能添加多次
subscriptions = new CopyOnWriteArrayList<>();
subscriptionsByEventType.put(eventType, subscriptions);
} else {
if (subscriptions.contains(newSubscription)) { //如果已經(jīng)存在
throw new EventBusException("Subscriber " + subscriber.getClass() + " already registered to event "
+ eventType);
}
}
int size = subscriptions.size(); //遍歷已經(jīng)存在的集合,根據(jù)他們的優(yōu)先級(jí)排序添加
for (int i = 0; i <= size; i++) {
if (i == size || subscriberMethod.priority > subscriptions.get(i).subscriberMethod.priority) { //優(yōu)先級(jí)由大到小排序
subscriptions.add(i, newSubscription);
break;
}
}
//typesBySubscriber緩存的是key:當(dāng)前訂閱類activity/fragment, value:當(dāng)前類中的訂閱方法的事件集合
List<Class<?>> subscribedEvents = typesBySubscriber.get(subscriber);
if (subscribedEvents == null) {
subscribedEvents = new ArrayList<>();
typesBySubscriber.put(subscriber, subscribedEvents);
}
subscribedEvents.add(eventType); //在當(dāng)前訂閱方法集合中加入當(dāng)前事件
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(); //查找當(dāng)前是當(dāng)前事件是緩存事件的父類則也會(huì)調(diào)用它的子類
for (Map.Entry<Class<?>, Object> entry : entries) {
Class<?> candidateEventType = entry.getKey();
if (eventType.isAssignableFrom(candidateEventType)) {
Object stickyEvent = entry.getValue();
checkPostStickyEventToSubscription(newSubscription, stickyEvent); //在注冊(cè)的時(shí)候就開始調(diào)用訂閱方法了,如果緩存隊(duì)列中存在
}
}
} else {
Object stickyEvent = stickyEvents.get(eventType);
checkPostStickyEventToSubscription(newSubscription, stickyEvent);
}
}
}
//checkPostStickyEventToSubscription
private void checkPostStickyEventToSubscription(Subscription newSubscription, Object stickyEvent) {
if (stickyEvent != null) {
// 一會(huì)兒post的時(shí)候還要研究這個(gè)方法
postToSubscription(newSubscription, stickyEvent, Looper.getMainLooper() == Looper.myLooper());
}
}
//new的一個(gè)訂閱類 Subscription 屬性包括
final class Subscription {
final Object subscriber; // 訂閱者對(duì)象
final SubscriberMethod subscriberMethod; // 訂閱方法
/**
* Becomes false as soon as {@link EventBus#unregister(Object)} is called, which is checked by queued event delivery
* {@link EventBus#invokeSubscriber(PendingPost)} to prevent race conditions.
*/
volatile boolean active; // 是否處于激活狀態(tài).如果不激活就不運(yùn)行哦
Subscription(Object subscriber, SubscriberMethod subscriberMethod) {
this.subscriber = subscriber;
this.subscriberMethod = subscriberMethod;
active = true; //新建的肯定是激活狀態(tài)
}
@Override
public boolean equals(Object other) {
if (other instanceof Subscription) {
Subscription otherSubscription = (Subscription) other;
return subscriber == otherSubscription.subscriber
&& subscriberMethod.equals(otherSubscription.subscriberMethod);
} else {
return false;
}
}
@Override
public int hashCode() {
return subscriber.hashCode() + subscriberMethod.methodString.hashCode();
}
}
復(fù)制代碼
- 總結(jié)訂閱方法: 由于上方已經(jīng)總結(jié)了對(duì)于一個(gè)訂閱類查找到它之中的所有訂閱方法以后循環(huán)調(diào)用subscribe繼續(xù)注冊(cè)
- 創(chuàng)建一個(gè)訂閱類,判斷是否存在以當(dāng)前事件為key的List<訂閱類>的集合,就是將所有相同的事件的訂閱類統(tǒng)一管理,這樣發(fā)送一個(gè)事件,只需要遍歷該集合即可知道回調(diào)那些類的哪些方法
- 注意加入到List集合時(shí)根據(jù)優(yōu)先級(jí)排序,由大到小,調(diào)用順序也是如此即可實(shí)現(xiàn)優(yōu)先級(jí)發(fā)送事件啦
- 對(duì)于訂閱類通過typesBySubscriber緩存: key當(dāng)前訂閱類,value:當(dāng)前訂閱類中所有事件類的集合
- 如果是粘性事件,判斷是否需要調(diào)取事件父類或接口對(duì)應(yīng)的訂閱方法,如果true且緩存中存在該事件的post,則直接執(zhí)行訂閱方法,否則只執(zhí)行當(dāng)前類中的訂閱方法(達(dá)到了先發(fā)送,后訂閱,且訂閱即運(yùn)行的目的,可以在Fragment中不通過intent對(duì)重新打開的Activity傳遞信息)
反注冊(cè)u(píng)nregister
- 有訂閱對(duì)應(yīng)的就有反注冊(cè),否則會(huì)內(nèi)存泄漏且多次注冊(cè)相同信息源碼中報(bào)錯(cuò)的
- 我們先思考一下,上方注冊(cè)的時(shí)候主要有兩個(gè)map集合,
- ypesBySubscriber表示key:訂閱類,value:訂閱類中的所有的事件類型集合;
- subscriptionsByEventType表示key: 事件類型 , value: 所有注冊(cè)該事件的訂閱方法集合
- 舉個(gè)例子,朋友圈A和B是好友,如果A要取關(guān)B,則A中有map(A , List好友們),在A中查找List好友將B刪除,同時(shí)在B中找到他的好友列表將A刪除即可啦
- 同樣的,對(duì)于上方兩個(gè)集合來說:我們也是反注冊(cè)時(shí)通過this訂閱類在ypesBySubscriber集合中找到該訂閱類中的所有事件類型的集合后,遍歷在subscriptionsByEventType中找到以當(dāng)前事件為key的value,訂閱方法集合中刪除該類對(duì)應(yīng)的訂閱方法即可啦
public synchronized void unregister(Object subscriber) {
List<Class<?>> subscribedTypes = typesBySubscriber.get(subscriber); //通過訂閱類獲取他當(dāng)中的所有訂閱事件類,我們加入的時(shí)候時(shí)加入事件類的class
if (subscribedTypes != null) {
for (Class<?> eventType : subscribedTypes) { //遍歷訂閱事件,開始解綁另外一個(gè)集合中的數(shù)據(jù):以eventType為key中刪除
unsubscribeByEventType(subscriber, eventType);
}
typesBySubscriber.remove(subscriber); //從當(dāng)前訂閱類為key的map移除
} else {
Log.w(TAG, "Subscriber to unregister was not registered before: " + subscriber.getClass());
}
}
private void unsubscribeByEventType(Object subscriber, Class<?> eventType) {
List<Subscription> subscriptions = subscriptionsByEventType.get(eventType); //獲取以當(dāng)前事件為key的所有訂閱方法集合
if (subscriptions != null) {
int size = subscriptions.size();
for (int i = 0; i < size; i++) {
Subscription subscription = subscriptions.get(i);
if (subscription.subscriber == subscriber) { //遍歷如果事件是在當(dāng)前類中訂閱的,則從訂閱方法集合中刪除,因?yàn)檫@個(gè)類就要over啦,自然也就不用再接受訂閱事件啦
subscription.active = false; //標(biāo)記不激活
subscriptions.remove(i); //從訂閱方法集合中刪除
i--;
size--;
}
}
}
}
復(fù)制代碼
post發(fā)送事件
- 通過上面的注冊(cè)和反注冊(cè)已經(jīng)將事件,訂閱方法都添加到集合中了,我們就可以發(fā)送一個(gè)事件開始響應(yīng)方法啦!
- 小知識(shí)點(diǎn): ThreadLocal是線程隔離的只有同一線程才能獲取值,通過get訪問,其他線程獲取不到的,同一個(gè)線程中才能獲取,且同一個(gè)線程獲取的是同一個(gè)對(duì)象
//ThreadLocal 的get方法
public T get() {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t); //如果已經(jīng)存在map則返回map中的值
if (map != null) {
ThreadLocalMap.Entry e = map.getEntry(this);
if (e != null) {
@SuppressWarnings("unchecked")
T result = (T)e.value;
return result;
}
}
return setInitialValue();
}
//調(diào)用initialValue創(chuàng)建一個(gè)對(duì)象值,存儲(chǔ)到map中,下次直接通過get即可獲取
private T setInitialValue() {
T value = initialValue();
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
createMap(t, value);
return value;
}
//上面簡單分析了ThreadLocal的源碼,下面開始真正的post操作
private final ThreadLocal<PostingThreadState> currentPostingThreadState = new ThreadLocal<PostingThreadState>() {
@Override
protected PostingThreadState initialValue() { //如果調(diào)用get方法沒有value值通過這個(gè)方法新建一個(gè)返回的,下次改線程在調(diào)用,已經(jīng)存在直接返回了,達(dá)到了對(duì)象的線程唯一性
return new PostingThreadState();
}
};
public void post(Object event) {
//代碼很短小,第一行就蒙蔽了,不急,就是上面我們說了get函數(shù)
PostingThreadState postingState = currentPostingThreadState.get(); //不同線程對(duì)應(yīng)不同的postingState,相同的線程之間遵循h(huán)appended-before
List<Object> eventQueue = postingState.eventQueue; //postingState中的eventQueue隊(duì)列
eventQueue.add(event); //將事件添加到隊(duì)列中:每個(gè)post線程的隊(duì)列都是相互獨(dú)立的
//isPosting默認(rèn)false,可以進(jìn)去
if (!postingState.isPosting) { //相同線程是遵循h(huán)appended-before規(guī)則的,是安全的
//是否是主進(jìn)程
postingState.isMainThread = Looper.getMainLooper() == Looper.myLooper();
postingState.isPosting = true; //阻擋不要在進(jìn)來了,表示當(dāng)前線程正在處理發(fā)送事件
if (postingState.canceled) { //沒有別取消事件
throw new EventBusException("Internal error. Abort state was not reset");
}
try {
while (!eventQueue.isEmpty()) { //輪詢開始發(fā)送事件
postSingleEvent(eventQueue.remove(0), postingState); //隊(duì)列,先進(jìn)先出
}
} finally {
postingState.isPosting = false; //完成恢復(fù)默認(rèn)可以在接受發(fā)送信息
postingState.isMainThread = false;
}
}
}
//靜態(tài)內(nèi)部類:每個(gè)線程獨(dú)一份
final static class PostingThreadState {
//事件隊(duì)列
final List<Object> eventQueue = new ArrayList<Object>();
boolean isPosting;
boolean isMainThread;
Subscription subscription;
Object event;
boolean canceled;
}
復(fù)制代碼
- post流程
- 首先通過ThreadLocal獲取當(dāng)前線程中狀態(tài)PostingState,注意不同的線程擁有不同的狀態(tài)PostingState
- 將發(fā)送的event加入到PostingState類中的隊(duì)列中
- 循環(huán)遍歷事件隊(duì)列,發(fā)送單個(gè)事件調(diào)用
- 發(fā)送單個(gè)Event的方法postSingleEvent
private void postSingleEvent(Object event, PostingThreadState postingState) throws Error {
Class<?> eventClass = event.getClass(); //獲取事件類型
boolean subscriptionFound = false;
if (eventInheritance) { //如果允許事件繼承,默認(rèn)允許
//找到eventClass的所有父類和實(shí)現(xiàn)接口
List<Class<?>> eventTypes = lookupAllEventTypes(eventClass);
int countTypes = eventTypes.size();
for (int h = 0; h < countTypes; h++) {
Class<?> clazz = eventTypes.get(h);
// 依次向 eventClass 的父類或接口的訂閱方法發(fā)送事件
// 只要有一個(gè)事件發(fā)送成功,返回 true 道盏,那么 subscriptionFound 就為 true
subscriptionFound |= postSingleEventForEventType(event, postingState, clazz);
}
} else {
//不允許繼承,那么只發(fā)送該事件
subscriptionFound = postSingleEventForEventType(event, postingState, eventClass);
}
if (!subscriptionFound) { //如果當(dāng)前沒有訂閱者訂閱
if (logNoSubscriberMessages) {
Log.d(TAG, "No subscribers registered for event " + eventClass);
}
//默認(rèn)允許的
if (sendNoSubscriberEvent && eventClass != NoSubscriberEvent.class &&
eventClass != SubscriberExceptionEvent.class) {
post(new NoSubscriberEvent(this, event)); //發(fā)送NosubSribeEvent事件,可以重寫訂閱方法接受到從而做自己的處理邏輯
}
}
}
//postSingleEventForEventType(event, postingState, eventClass)參數(shù): 事件對(duì)象里面可能有值, 當(dāng)前線程的狀態(tài)postingState, 事件類型class
private boolean postSingleEventForEventType(Object event, PostingThreadState postingState, Class<?> eventClass) {
CopyOnWriteArrayList<Subscription> subscriptions;
synchronized (this) {
subscriptions = subscriptionsByEventType.get(eventClass); //獲取以當(dāng)前事件為key的訂閱類的集合(屬性: 訂閱類,訂閱方法,是否激活)
}
if (subscriptions != null && !subscriptions.isEmpty()) {
for (Subscription subscription : subscriptions) { //還記得添加由大->小,這里取值是由0->size實(shí)現(xiàn)優(yōu)先級(jí),同時(shí)event對(duì)象不可變,但是每個(gè)共用同一個(gè)event,里面的屬性值是可以更改的
postingState.event = event;
postingState.subscription = subscription;
boolean aborted = false;
try {
//發(fā)送事件,參數(shù)subscription訂閱類信息,event發(fā)送事件對(duì)象, 是否是主線程
postToSubscription(subscription, event, postingState.isMainThread);
//是否被取消了
aborted = postingState.canceled;
} finally {
postingState.event = null; //回復(fù)默認(rèn)值
postingState.subscription = null;
postingState.canceled = false;
}
if (aborted) { // 如果被取消而柑,則跳出循環(huán)
break;
}
}
return true; //有一個(gè)發(fā)送成功即可,對(duì)應(yīng)上面的判斷
}
return false;
}
//postToSubscription: isMainThread 表示發(fā)送方法是否在主線程中
private void postToSubscription(Subscription subscription, Object event, boolean isMainThread) {
switch (subscription.subscriberMethod.threadMode) { //接受事件的訂閱方法所在的線程
case POSTING: //那個(gè)線程發(fā)送就在那個(gè)線程接受
invokeSubscriber(subscription, event);
break;
case MAIN:
if (isMainThread) {
invokeSubscriber(subscription, event); //在主線程中接受
} else { //其他線程向主線程發(fā)送添加到隊(duì)列(鏈表)后通過Handler一次發(fā)送隊(duì)列中的值給UI線程最終調(diào)用的還是invokeSubscriber(subscription, event)方法
//PendingPost添加隊(duì)列獲取是通過PendingPost對(duì)象池,同Message相同的
mainThreadPoster.enqueue(subscription, event);
}
break;
case BACKGROUND:
if (isMainThread) { //如果在子線程中發(fā)送,則隨機(jī)開辟一條子線程接收
backgroundPoster.enqueue(subscription, event);
} else { //在子線程中發(fā)送,在相同的線程中接收
invokeSubscriber(subscription, event);
}
break;
case ASYNC: //無論是UI還是子線程,都會(huì)開辟一個(gè)新的線程接收
asyncPoster.enqueue(subscription, event);
break;
default:
throw new IllegalStateException("Unknown thread mode: " + subscription.subscriberMethod.threadMode);
}
}
//invokeSubscriber參數(shù): subscription訂閱類信息: 訂閱類,方法,是否激活信息
void invokeSubscriber(Subscription subscription, Object event) {
try {
//反射調(diào)用方法: method.invoke(class, 參數(shù)信息)即可,在哪個(gè)線程調(diào)用就運(yùn)行在哪個(gè)線程
subscription.subscriberMethod.method.invoke(subscription.subscriber, event);
} catch (InvocationTargetException e) {
handleSubscriberException(subscription, event, e.getCause()); //如果沒有找到就發(fā)送錯(cuò)誤事件,重寫即可監(jiān)聽到
} catch (IllegalAccessException e) {
throw new IllegalStateException("Unexpected exception", e);
}
}
復(fù)制代碼
- 我們看一下線程之間是如何做的吧!
- 主線程的mainThreadPoster.equeue()
//在EventBus中創(chuàng)建的
mainThreadPoster = new HandlerPoster(this, Looper.getMainLooper(), 10);
final class HandlerPoster extends Handler {
private final PendingPostQueue queue; //事件隊(duì)列
private final int maxMillisInsideHandleMessage;
private final EventBus eventBus;
private boolean handlerActive;
HandlerPoster(EventBus eventBus, Looper looper, int maxMillisInsideHandleMessage) {
super(looper);
this.eventBus = eventBus;
this.maxMillisInsideHandleMessage = maxMillisInsideHandleMessage;
queue = new PendingPostQueue(); //每個(gè)線程都有他自己的時(shí)間隊(duì)列
}
void enqueue(Subscription subscription, Object event) {
//獲取很有意思,所有線程共用同一個(gè)對(duì)象池,當(dāng)存在可用返回,否則新建,回收的時(shí)候添加到池中,了解過Message消息對(duì)象的很熟悉啦
PendingPost pendingPost = PendingPost.obtainPendingPost(subscription, event);
synchronized (this) {
queue.enqueue(pendingPost); //加入隊(duì)列
if (!handlerActive) {
handlerActive = true;
if (!sendMessage(obtainMessage())) { //發(fā)送事件封裝類
throw new EventBusException("Could not send handler message");
}
}
}
}
@Override
public void handleMessage(Message msg) {
boolean rescheduled = false;
try {
long started = SystemClock.uptimeMillis();
while (true) {
PendingPost pendingPost = queue.poll();
if (pendingPost == null) {
synchronized (this) {
// Check again, this time in synchronized
pendingPost = queue.poll();
if (pendingPost == null) {
handlerActive = false;
return;
}
}
}
eventBus.invokeSubscriber(pendingPost); //UI線程取出來調(diào)用invokeSubscriber方法
long timeInMethod = SystemClock.uptimeMillis() - started;
if (timeInMethod >= maxMillisInsideHandleMessage) {
if (!sendMessage(obtainMessage())) {
throw new EventBusException("Could not send handler message");
}
rescheduled = true;
return;
}
}
} finally {
handlerActive = rescheduled;
}
}
}
//Event中的方法
void invokeSubscriber(PendingPost pendingPost) {
Object event = pendingPost.event;
Subscription subscription = pendingPost.subscription;
PendingPost.releasePendingPost(pendingPost); //回收對(duì)象到對(duì)象池中以便下一個(gè)運(yùn)用
if (subscription.active) { //如果當(dāng)前激活狀態(tài),則反射調(diào)用方法即可
invokeSubscriber(subscription, event);
}
}
//類的靜態(tài)常量,所有線程共用同一個(gè)
private final static List<PendingPost> pendingPostPool = new ArrayList<PendingPost>();
復(fù)制代碼
- 直到現(xiàn)在我們還沒有用到線程池的概念吧,這個(gè)時(shí)候你是不是都忘記了EventBus構(gòu)造函數(shù)中創(chuàng)建了一個(gè)線程池newCacheExecutor() 可能導(dǎo)致OOM,看一下backgroundPoster.enqueue(subscription, event);
//EventBus構(gòu)造函數(shù)中創(chuàng)建
backgroundPoster = new BackgroundPoster(this);
final class BackgroundPoster implements Runnable { //代碼量不多,整個(gè)拿過來
private final PendingPostQueue queue; //時(shí)間隊(duì)列
private final EventBus eventBus;
private volatile boolean executorRunning;
BackgroundPoster(EventBus eventBus) {
this.eventBus = eventBus;
queue = new PendingPostQueue();
}
public void enqueue(Subscription subscription, Object event) {
//通過事件封裝對(duì)象池獲取對(duì)象
PendingPost pendingPost = PendingPost.obtainPendingPost(subscription, event);
synchronized (this) {
queue.enqueue(pendingPost); //添加一個(gè)到隊(duì)列中,下面就可以執(zhí)行了
if (!executorRunning) { //線程池是否正在運(yùn)行
executorRunning = true;
//調(diào)用EventBus中創(chuàng)建的線程池執(zhí)行該類的run方法
eventBus.getExecutorService().execute(this);
}
}
}
@Override
public void run() {
try {
try {
while (true) {
PendingPost pendingPost = queue.poll(1000);
if (pendingPost == null) { //雙重檢索隊(duì)列中還沒有新加則退出,開始回收線程
synchronized (this) {
// Check again, this time in synchronized
pendingPost = queue.poll();
if (pendingPost == null) {
executorRunning = false;
return;
}
}
}
//線程池的一個(gè)線中程執(zhí)行方法,同上方的Ui線程一致的,反射調(diào)用執(zhí)行方法即可,無非就是運(yùn)行線程不同,這個(gè)是子線程,上面的是UI線程
eventBus.invokeSubscriber(pendingPost);
}
} catch (InterruptedException e) {
Log.w("Event", Thread.currentThread().getName() + " was interruppted", e);
}
} finally {
executorRunning = false;
}
}
}
// asyncPoster.enqueue(subscription, event);同樣是在EventBus構(gòu)造方法中創(chuàng)建的
class AsyncPoster implements Runnable { //類比較簡單
private final PendingPostQueue queue;
private final EventBus eventBus;
AsyncPoster(EventBus eventBus) {
this.eventBus = eventBus;
queue = new PendingPostQueue();
}
public void enqueue(Subscription subscription, Object event) {
PendingPost pendingPost = PendingPost.obtainPendingPost(subscription, event);
queue.enqueue(pendingPost);
eventBus.getExecutorService().execute(this);
}
@Override
public void run() {
PendingPost pendingPost = queue.poll(); //通過子線程直接運(yùn)行即可
if(pendingPost == null) {
throw new IllegalStateException("No pending post available");
}
eventBus.invokeSubscriber(pendingPost);
}
}
復(fù)制代碼
- 通過上面分析,equeue添加是一個(gè)個(gè)添加,一個(gè)個(gè)執(zhí)行,通過executorRunning變量控制著,如果run執(zhí)行中耗時(shí)過長,添加的特別迅速,線程池將會(huì)創(chuàng)建大量線程,最終可能OOM
- Posting: 表示post線程在哪兒發(fā)送,接受的就是該線程
- Main: 如果在主線程中發(fā)送,則直接執(zhí)行接受,否則利用Handler回調(diào)到主線程中執(zhí)行
- BackGround子線程: 如果發(fā)布事件在主線程,則調(diào)用線程池中的一個(gè)子線程去執(zhí)行,否則直接在發(fā)送線程中執(zhí)行
- (ASYNC)異步線程: 無論發(fā)布事件是UI還是子線程都利用一個(gè)異步線程來執(zhí)行!
- 注意:以上所有的方法分析都是在Post()方法內(nèi)部調(diào)用邏輯,所以線程切換需要注意是否是線程池創(chuàng)建還是原來的post方法所在的線程之內(nèi)
配置索引
- EventBus3.0以后為了提高效率避免在運(yùn)行期通過反射來做以上大量的工作,使用了索引配置生成類,可以在編譯器生成注冊(cè)文件,從而提升效率
- 使用:兩種方式:使用android-apt三方插件,或者annotationProcessor
//1.使用android-apt
buildscript {
dependencies {
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
}
}
apply plugin: 'com.neenbedankt.android-apt'
dependencies {
compile 'org.greenrobot:eventbus:3.0.0'
apt 'org.greenrobot:eventbus-annotation-processor:3.0.1'
}
apt {
arguments {
eventBusIndex "com.monster.android.wild.MyEventBusIndex"
}
}
//2\. 使用annotationProcessor
android {
defaultConfig {
javaCompileOptions {
annotationProcessorOptions {
arguments = [eventBusIndex:'com.monster.android.wild.MyEventBusIndex']
}
}
}
}
dependencies {
compile 'org.greenrobot:eventbus:3.0.0'
annotationProcessor 'org.greenrobot:eventbus-annotation-processor:3.0.1'
}
復(fù)制代碼
- com.monster.android.wild.MyEventBusIndex就是我們想要生成的Subscriber Index類
public class MyEventBusIndex implements SubscriberInfoIndex {
private static final Map<Class<?>, SubscriberInfo> SUBSCRIBER_INDEX; //緩存mao:key當(dāng)前訂閱類 , 值是封裝的SimpleSubscriberInfo類(訂閱類,應(yīng)該檢查父類,該訂閱類中對(duì)應(yīng)的訂閱方法的數(shù)組)
static {
SUBSCRIBER_INDEX = new HashMap<Class<?>, SubscriberInfo>();
// 從以上createInfoIndexFile()的實(shí)現(xiàn)來看,除了類名MyEventBusIndex荷逞,只有這一段代碼是非hardcode媒咳。編譯器自動(dòng)生成的代碼
// 以訂閱者類為單位,將該訂閱者類中的所有訂閱函數(shù)以及相關(guān)參數(shù)种远,封裝到SimpleSubscriberInfo類對(duì)象中涩澡,
// 以供EventBus在注冊(cè)過程中使用。注意SimpleSubscriberInfo類對(duì)象是在編譯時(shí)期就生成的坠敷,
// 因而在運(yùn)行時(shí)期可以直接使用妙同,省去了運(yùn)行時(shí)期通過反射做相似操作的時(shí)間和資源消耗射富,從而提高效率,這里就是全文的精髓所在粥帚。
putIndex(new SimpleSubscriberInfo(com.monster.android.wild.myeventbusdemo.MainActivity.class, true,
new SubscriberMethodInfo[] {
new SubscriberMethodInfo("onEvent",
com.monster.android.wild.myeventbusdemo.MainActivity.EventBusEvent.class, ThreadMode.MAIN),
}));
}
private static void putIndex(SubscriberInfo info) {
SUBSCRIBER_INDEX.put(info.getSubscriberClass(), info);
}
// 將會(huì)在EventBus在注冊(cè)過程中使用胰耗,等會(huì)大家會(huì)看到
@Override
public SubscriberInfo getSubscriberInfo(Class<?> subscriberClass) {
SubscriberInfo info = SUBSCRIBER_INDEX.get(subscriberClass);
if (info != null) {
return info;
} else {
return null;
}
}
}
復(fù)制代碼
- 上面register中有兩個(gè)分支,通過ignoreGeneratedIndex是否直接使用反射調(diào)用區(qū)分,我們當(dāng)時(shí)走的是第一個(gè)findUsingReflection,下面看添加索引后的第二個(gè)方法findUsingInfo
private List<SubscriberMethod> findUsingInfo(Class<?> subscriberClass) {
FindState findState = prepareFindState();
findState.initForSubscriber(subscriberClass); //findstate數(shù)組中準(zhǔn)備并初始化FindState對(duì)象
while (findState.clazz != null) {
//重點(diǎn),重點(diǎn),重點(diǎn): 通過索引獲取編譯器生成的訂閱者信息
findState.subscriberInfo = getSubscriberInfo(findState);
if (findState.subscriberInfo != null) { //注意這里的subscriberInfo實(shí)際上是系統(tǒng)自動(dòng)生成的類SimpleSubscriberInfo對(duì)象 //如果找到了就遍歷訂閱類中的訂閱方法數(shù)組加入進(jìn)去
SubscriberMethod[] array = findState.subscriberInfo.getSubscriberMethods(); //調(diào)用SimpleSubscriberInfo.getSubscriberMethods方法獲取訂閱方法集合封裝成SubscriberMethod[]
for (SubscriberMethod subscriberMethod : array) { //輪詢,下面就跟反射是一致的操作了
if (findState.checkAdd(subscriberMethod.method, subscriberMethod.eventType)) {
findState.subscriberMethods.add(subscriberMethod);
}
}
} else { //否則還是老實(shí)的回到反射注冊(cè)上面去吧
findUsingReflectionInSingleClass(findState);
}
findState.moveToSuperclass();
}
return getMethodsAndRelease(findState); //回收findState對(duì)象,以便下次使用
}
//getSubscriberInfo
private SubscriberInfo getSubscriberInfo(FindState findState) {
if (findState.subscriberInfo != null && findState.subscriberInfo.getSuperSubscriberInfo() != null) { //新建的findState為null
SubscriberInfo superclassInfo = findState.subscriberInfo.getSuperSubscriberInfo();
if (findState.clazz == superclassInfo.getSubscriberClass()) {
return superclassInfo;
}
}
//subscriberInfoIndexes是在合適創(chuàng)建的
if (subscriberInfoIndexes != null) { //subscriberInfoIndexes可能添加多個(gè)文件信息,這里我們只是一個(gè)
for (SubscriberInfoIndex index : subscriberInfoIndexes) {
//拿到唯一的一個(gè)index類即index為: MyEventBusIndex類對(duì)象
SubscriberInfo info = index.getSubscriberInfo(findState.clazz); //調(diào)用它的getSubscriberInfo(訂閱類)即可獲得已經(jīng)put進(jìn)緩存SUBSCRIBER_INDEX中的方法封裝類SimpleSubscriberInfo
if (info != null) {
return info;
}
}
}
return null;
}
//通過EventBus構(gòu)造函數(shù)中創(chuàng)建通過build傳遞進(jìn)來的,如果我們使用索引并且重寫build方法傳遞進(jìn)來數(shù)據(jù)了
subscriberMethodFinder = new SubscriberMethodFinder(builder.subscriberInfoIndexes,
builder.strictMethodVerification, builder.ignoreGeneratedIndex);
//將索引值穿進(jìn)去
EventBus eventBus = EventBus.builder().addIndex(new MyEventBusIndex()).build();
復(fù)制代碼
-
至此:無論是直接反射注冊(cè)還是通過添加索引在編譯器生成文件運(yùn)行期直接讀取注冊(cè)都分析完成了,不知道你明白了沒有呢?最后的話也整理了一份《Android相關(guān)源碼精編解析》,方便大家筆記學(xué)習(xí),有需要的朋友可以點(diǎn)贊+評(píng)論支持下,然后評(píng)論留言或私信我獲取!