EventBus源码分析
簡(jiǎn)介
前面我學(xué)習(xí)了如何使用EventBus,還有了解了EventBus的特性,那么接下來(lái)我們一起來(lái)學(xué)習(xí)EventBus的源碼,查看EventBus的源碼,看看EventBus給我們帶來(lái)什么驚喜以及編程思想。
這個(gè)圖我們從一開(kāi)始就一直放置在上面了。我們?cè)趤?lái)回顧一下,EventBus的官網(wǎng)是怎么定義它的呢?
EventBus是Android和Java的發(fā)布/訂閱(觀察者模式)事件總線。
我們大概了解了EventBus的構(gòu)建思想。接下來(lái)我們進(jìn)入源碼學(xué)習(xí)吧。
進(jìn)入源碼分析
我們從EventBus的注冊(cè)開(kāi)始入手。
EventBus.getDefault().register(this); public static EventBus getDefault() {if (defaultInstance == null) {synchronized (EventBus.class) {if (defaultInstance == null) {//創(chuàng)建了EventBus實(shí)例,進(jìn)入下面的方法defaultInstance = new EventBus(); }}}return defaultInstance;}上面的方法是一個(gè)雙重校驗(yàn)的單例。
public EventBus() {this(DEFAULT_BUILDER); //private static final EventBusBuilder DEFAULT_BUILDER = new EventBusBuilder();}DEFAULT_BUILDER是EventBusBuilder.class實(shí)例來(lái)創(chuàng)建的,這個(gè)類非常重要:使用自定義參數(shù)創(chuàng)建EventBus實(shí)例,還允許自定義默認(rèn)EventBus實(shí)例,如前面的例子使用索引、配置EventBus的配置&事件的優(yōu)先級(jí)&使用索引(四)等就是通過(guò)這個(gè)類來(lái)實(shí)現(xiàn)的,大家可以回顧一下。進(jìn)入初始化一下必要的參數(shù)的構(gòu)造方法EventBus(EventBusBuilder builder),如下
EventBus(EventBusBuilder builder) {logger = builder.getLogger(); /初始化LoggersubscriptionsByEventType = new HashMap<>(); //存儲(chǔ)訂閱事件的typesBySubscriber = new HashMap<>(); //存儲(chǔ)相關(guān)訂閱者class列表,key是注冊(cè)者的對(duì)象,value是訂閱者的class列表stickyEvents = new ConcurrentHashMap<>(); //粘性事件//下面這4個(gè)實(shí)例就是我們?cè)O(shè)置方法``threadMode = ThreadMode.xxx``//*1mainThreadSupport = builder.getMainThreadSupport();mainThreadPoster = mainThreadSupport != null ? mainThreadSupport.createPoster(this) : null;backgroundPoster = new BackgroundPoster(this);asyncPoster = new AsyncPoster(this);//獲取注冊(cè)者信息索引(添加由EventBus的注釋預(yù)處理器生成的索引)indexCount = builder.subscriberInfoIndexes != null ? builder.subscriberInfoIndexes.size() : 0;//初始訂閱方法查找器。這個(gè)類主要具有查找訂閱的方法,繼續(xù)往下看subscriberMethodFinder = new SubscriberMethodFinder(builder.subscriberInfoIndexes,builder.strictMethodVerification, builder.ignoreGeneratedIndex);logSubscriberExceptions = builder.logSubscriberExceptions; //是否有日記訂閱,默認(rèn)truelogNoSubscriberMessages = builder.logNoSubscriberMessages;//是否有日記信息,默認(rèn) truesendSubscriberExceptionEvent = builder.sendSubscriberExceptionEvent;//是否發(fā)送訂閱異常事件,默認(rèn)truesendNoSubscriberEvent = builder.sendNoSubscriberEvent; //是否發(fā)送沒(méi)有訂閱事件,默認(rèn)truethrowSubscriberException = builder.throwSubscriberException; //是否拋出異常處理//默認(rèn)情況下,EventBus會(huì)考慮事件類層次結(jié)構(gòu)(將通知超類的注冊(cè)者)。 關(guān)閉此功能將改善事件的發(fā)布。對(duì)于直接擴(kuò)展Object的簡(jiǎn)單事件類,我們測(cè)量事件發(fā)布的速度提高了20%。eventInheritance = builder.eventInheritance; executorService = builder.executorService; //創(chuàng)建線程池}我們將此段代碼逐步分析.
這步主要是進(jìn)行初始化話一下必要的參數(shù),如代碼注解所示。
下面這段代碼就是我們常用的@Subscribe(threadMode = ThreadMode.xxx);初始化。一般常用的就是以下4種。
我們來(lái)看看builder.getMainThreadSupport()方法返回的是MainThreadSupport接口,表示為支持Android主線程。
上面的4個(gè)線程中都持有 PendingPostQueue 等待發(fā)送的隊(duì)列實(shí)例。
由mainThreadSupport.createPoster(this)創(chuàng)建一個(gè)HandlerPoster而該類繼承了Handle,并且初始化了一個(gè)等待發(fā)布隊(duì)列。代碼如下。
上面代碼在這里主要初始化訂閱的方法查找器。下面會(huì)講解到它是如何進(jìn)行訂閱方法的。
我們這這里知道了EventBus初始化,然后相關(guān)的實(shí)例的創(chuàng)建,接下來(lái)我我們進(jìn)入到register(this)方法的調(diào)用如下方法。
上面的代碼表示的是給注冊(cè)者接收事件。 傳遞當(dāng)前所注冊(cè)的對(duì)象,如Activity、Fragment。
- 注意: 注冊(cè)者如果不再接收信息,必須調(diào)用unregister(Object)方法,表示解除注冊(cè)則該訂閱者將不再接收到數(shù)據(jù)了,如果不進(jìn)行解除將可能出現(xiàn)內(nèi)存泄漏。一般在onDestroy方法解除注冊(cè)后面會(huì)講解到。 在注冊(cè)者中擁有必須由@Subscribe注解的方法。@Subscribe還允許配置ThreadMode和優(yōu)先級(jí)、是否是粘性行為。
接著,我們進(jìn)入List<SubscriberMethod> subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass);方法。
//private static final Map<Class<?>, List<SubscriberMethod>> METHOD_CACHE = new ConcurrentHashMap<>(); //線程安全List<SubscriberMethod> findSubscriberMethods(Class<?> subscriberClass) {//從Map集合中獲取訂閱方法列表List<SubscriberMethod> subscriberMethods = METHOD_CACHE.get(subscriberClass);//判斷當(dāng)前獲取方法是否為空if (subscriberMethods != null) {return subscriberMethods;}//通過(guò)EventBusBuilder.ignoreGeneratedIndex//是否忽略配置索引,默認(rèn)是忽略索引if (ignoreGeneratedIndex) {//1.通過(guò)反射獲取方法列表subscriberMethods = findUsingReflection(subscriberClass);} else {//2.通過(guò)索引方式獲取訂閱方法列表subscriberMethods = findUsingInfo(subscriberClass);}//是否訂閱方法為空,如果為空則表示該訂閱者里面的方法都不符合EventBus訂閱方法的規(guī)則if (subscriberMethods.isEmpty()) {throw new EventBusException("Subscriber " + subscriberClass+ " and its super classes have no public methods with the @Subscribe annotation");} else {//存儲(chǔ)到集合中METHOD_CACHE.put(subscriberClass, subscriberMethods);return subscriberMethods;} }我們逐步分析該段代碼。
該段代碼通過(guò)注冊(cè)者的類來(lái)獲取當(dāng)前dingy的方法列表,如果不為空則直接返回訂閱方法。
通過(guò)反射來(lái)查找訂閱方法,如果該方法為空則拋出異常:該訂閱者的方法和其超類沒(méi)有@Subscriber注解的共有方法(即表示不符合EventBus訂閱方法的規(guī)則)。如果不為空則存儲(chǔ)到ConcurrentHashMap集合中。
這里的是由ConcurrentHashMap集合存儲(chǔ)是以當(dāng)前訂閱者的class為key,而將其由@Subscriber綁定的方法添加到List中,,就是集合的value。必須保持線程安全的,所以這里使用了ConcurrentHashMap。
- 1.是否忽略索引設(shè)置,該方法表示忽略設(shè)置索引,進(jìn)入該方法findUsingReflection(Class<?> subscriberClass),通過(guò)反射進(jìn)行獲取List<SubscriberMethod>
- 注:設(shè)置索引在EventBus的配置&事件的優(yōu)先級(jí)&使用索引(四)這里說(shuō)的,大家可以去看看。
上面的代碼主要是通過(guò)反射來(lái)獲取相關(guān)的訂閱方法,里面由靜態(tài)內(nèi)部類FindState進(jìn)行管理相關(guān)信息,由于上面的方法和下面索引的方法都將調(diào)用同一個(gè)方法,所以放在下面來(lái)將講解,請(qǐng)看下面信息。
- 2.是否忽略索引設(shè)置,該方法表示的設(shè)置了索引,進(jìn)入findUsingInfo(Class<?> subscriberClass)方法,如下。
分析本段代碼。
首先進(jìn)入查找的準(zhǔn)備狀態(tài),通過(guò)默認(rèn)狀態(tài)池返回狀態(tài)信息,主要存儲(chǔ)的是FindState實(shí)例。主要存儲(chǔ)的有訂閱者的class、訂閱者信息SubscriberInfo。訂閱者@Subscribe方法列表List<SubscriberMethod>等.
如果當(dāng)前訂閱者class不為空,則將獲取到訂閱者信息。這里分兩種情況。
如果使用添加索引的話,getSubscriberInfo(findState)該方法將獲取到訂閱信息,如果沒(méi)有使用索引的話則將調(diào)用findUsingReflectionInSingleClass(findState);該方法來(lái)獲取信息
- 使用添加索引,并返回訂閱方法,該方法如下
由于AbstractSubscriberInfo類實(shí)現(xiàn)了SubscriberInfo接口,而SimpleSubscriberInfo繼承了AbstractSubscriberInfo并實(shí)現(xiàn)了getSubscriberMethods方法,代碼如下:
本段代碼在SimpleSubscriberInfo.class中。返回訂閱方法數(shù)組SubscriberMethod[]。
- 3.如果沒(méi)有添加索引則進(jìn)入該方法findUsingReflectionInSingleClass(findState);
通過(guò)反射來(lái)獲取訂閱者方法。這個(gè)方法有點(diǎn)長(zhǎng),慢慢看。
private void findUsingReflectionInSingleClass(FindState findState) {Method[] methods;try {// This is faster than getMethods, especially when subscribers are fat classes like Activities//該方法代替getMethods()方法,獲取該訂閱者class全部方法。methods = findState.clazz.getDeclaredMethods();} catch (Throwable th) {// Workaround for java.lang.NoClassDefFoundError, see https://github.com/greenrobot/EventBus/issues/149methods = findState.clazz.getMethods(); //獲取該訂閱者class全部方法findState.skipSuperClasses = true; //設(shè)置跳過(guò)超類}for (Method method : methods) {int modifiers = method.getModifiers();//獲取修飾符if ((modifiers & Modifier.PUBLIC) != 0 && (modifiers & MODIFIERS_IGNORE) == 0) { //通過(guò)與運(yùn)算判斷當(dāng)前的修飾符,是否符合EventBus方法定義Class<?>[] parameterTypes = method.getParameterTypes(); //獲取參數(shù)類型if (parameterTypes.length == 1) { //因?yàn)镋ventBus方法中必須有參數(shù),所以當(dāng)參數(shù)為1時(shí),符合要求//通過(guò)注解的形式@Subscribe獲取Subscribe,默認(rèn)的Subscribe為(priority==0,sticky=false,threadMode=POSTING),就是說(shuō)ThreadMode為POSTING,粘性為false,優(yōu)先級(jí)為0,如果方法中設(shè)置了相應(yīng)的值,則將是你設(shè)置的值。如threadMode=MAIN。Subscribe subscribeAnnotation = method.getAnnotation(Subscribe.class);if (subscribeAnnotation != null) {Class<?> eventType = parameterTypes[0]; //獲取當(dāng)前參數(shù)的class//進(jìn)行等級(jí)檢查,并存儲(chǔ)到Map集合中,該方法checkAdd是FindState.class中的方法 ,key是@Subscriber中參數(shù)的class,value是該subscriberMethod.method,也就是@Subscribe中的方法如:public void onMessageEvent(MessageEvent event)if (findState.checkAdd(method, eventType)) { // 獲取ThreadMode ,如MAINThreadMode threadMode = subscribeAnnotation.threadMode();//將訂閱方法添加到列表中findState.subscriberMethods.add(new SubscriberMethod(method, eventType, threadMode,subscribeAnnotation.priority(), subscribeAnnotation.sticky()));}}} else if (strictMethodVerification && method.isAnnotationPresent(Subscribe.class)) { //不符合EventBus訂閱方法的規(guī)則要求。拋出異常,提示該方法必須是@Subscribe注解,并且需要一個(gè)參數(shù)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)) {//是一種非法的@Subscribe方法:必須是公共的,非靜態(tài)的,非抽象的String methodName = method.getDeclaringClass().getName() + "." + method.getName();throw new EventBusException(methodName +" is a illegal @Subscribe method: must be public, non-static, and non-abstract");}}}該段代碼主要是獲取該注冊(cè)者的全部方法,并進(jìn)行篩選出來(lái)符合EventBus的訂閱方法的規(guī)則,通過(guò)注解的形式來(lái)獲取訂閱方法,最后添加到查找狀態(tài)的列表中。
首先獲取的是修飾符,參數(shù)類型,再通過(guò)注解的形式來(lái)獲取訂閱方法。如下注解Subscribe ,如果不符合EventBus相關(guān)訂閱方法的規(guī)則將拋出異常提示,是否在方法上書(shū)寫(xiě)了錯(cuò)誤的方法。
接下來(lái)我們進(jìn)入看看@Subscribe 訂閱方法是通過(guò)注解的形式來(lái)設(shè)置的。
接下來(lái)進(jìn)入getMethodsAndRelease(FindState findState)
private List<SubscriberMethod> getMethodsAndRelease(FindState findState) {//獲取到訂閱方法列表List<SubscriberMethod> subscriberMethods = new ArrayList<>(findState.subscriberMethods); findState.recycle(); //清空回收相關(guān)信息synchronized (FIND_STATE_POOL) {for (int i = 0; i < POOL_SIZE; i++) {if (FIND_STATE_POOL[i] == null) {FIND_STATE_POOL[i] = findState; //將查找狀態(tài)器findState,添加到狀態(tài)池FIND_STATE_POOL中,為下次直接從查找狀態(tài)池中獲取break;}}}return subscriberMethods; // 返回訂閱方法列表}上面該方法通過(guò)FindState靜態(tài)內(nèi)部類獲取了訂閱的列表,然后被存儲(chǔ)到了ConcurrentHashMap集合中。并且存儲(chǔ)到狀態(tài)池中,為方便下次讀取。并且回收資源。
獲取到List<SubscriberMethod>訂閱列表后,再次回到了注冊(cè)方法中register(Object subscriber)進(jìn)入到方法subscribe(subscriber, subscriberMethod);該方法通過(guò)循環(huán)進(jìn)行遍歷
- 注 此處必須是在線程同步中進(jìn)行,所以添加synchronized。
上面的方法中主要是通過(guò)獲取"事件類型"即訂閱方法中的參數(shù)class。然后將其添加到Map集合中,這里用到了CopyOnWriteArrayList(原理:是寫(xiě)時(shí)復(fù)制容器,即當(dāng)我們往CopyOnWriteArrayList容器添加元素時(shí),先從原有的數(shù)組中拷貝一份出來(lái),然后在新的容器做寫(xiě)操作(添加元素),寫(xiě)完之后,再將原來(lái)的數(shù)組引用指向到新數(shù)組的形式存儲(chǔ)數(shù)據(jù)的,它是線程安全的。)
然后進(jìn)行判斷是否設(shè)置優(yōu)先級(jí),遍歷并添加到subscriptions列表中。
通過(guò)當(dāng)前的注冊(cè)者,獲取注冊(cè)者class列表,并添加到typesBySubscriber集合中,key是注冊(cè)者的class,如:Activity,而value就是訂閱方法中的參數(shù)class的列表。這個(gè)地方說(shuō)明了,一個(gè)注冊(cè)者,可以擁有多個(gè)訂閱事件(方法),將其綁定起來(lái),存儲(chǔ)到Map集合中。最后將該參數(shù)class添加到subscribedEvents.add(eventType);列表中。
下面方法是檢查粘性事件訂閱發(fā)送事件方法,如下
- 注:這里主要是檢查是否發(fā)送粘性發(fā)送事件,方法 postToSubscription我們到發(fā)送事件POST方法調(diào)用時(shí)講解。
- 事件發(fā)送
接下來(lái)我進(jìn)入post方法,事件發(fā)送。此時(shí),我們回憶一下簡(jiǎn)介中的圖:
post()==>EventBus==>將分發(fā)到各個(gè)訂閱事件中。也就是訂閱方法。我們來(lái)看看是如何進(jìn)行操作的。代碼如下
通過(guò)以上代碼我大概的知道,post()方法里面的參數(shù)是一個(gè)實(shí)體的對(duì)象,而該實(shí)體就是我們?cè)谟嗛喎椒ㄖ械膮?shù)實(shí)體。你發(fā)現(xiàn)了什么了嗎?
前邊我們已經(jīng)分析了,該注冊(cè)者的訂閱方法主要的存儲(chǔ)過(guò)程,接下來(lái)我們一起進(jìn)入探究吧。方法跟蹤進(jìn)入post()方法。
currentPostingThreadState.get()方法中我們知道
private final ThreadLocal<PostingThreadState> currentPostingThreadState = new ThreadLocal<PostingThreadState>() {@Overrideprotected PostingThreadState initialValue() {return new PostingThreadState();}};通過(guò)ThreadLocal這里就叫"本地線程"吧,來(lái)管理當(dāng)前的發(fā)送線程狀態(tài),每個(gè)發(fā)送線程將得到對(duì)應(yīng)一個(gè)PostingThreadState,而該P(yáng)ostingThreadState管理eventQueue信息,該信息主要存儲(chǔ)的是發(fā)送事件。
通過(guò)eventQueue.add(event)存儲(chǔ)該發(fā)送事件以后完成以后,就判斷當(dāng)前的發(fā)送事件狀態(tài)是否是正在發(fā)送中,如果還沒(méi)發(fā)送則當(dāng)該eventQueue不為為空的時(shí)候,進(jìn)入循環(huán)發(fā)送該事件,發(fā)送完一個(gè)就刪除一個(gè),直到發(fā)送完成為止。
進(jìn)入方法postSingleEvent(Object event, PostingThreadState postingState)中。
上面的方法首先獲取該事件類型的class然后傳遞到lookupAllEventTypes(eventClass)方法中,通過(guò)該方法獲取當(dāng)前發(fā)送事件的class,包括父類、實(shí)現(xiàn)的接口等等列表。所以一般情況下會(huì)返回當(dāng)前發(fā)送的事件,和Object.class(注:當(dāng)然了,如果該事件實(shí)現(xiàn)接口的話,也會(huì)包括實(shí)現(xiàn)的接口的。)列表即List<Class<?>>,然后進(jìn)行遍歷進(jìn)行或運(yùn)算。
我們先進(jìn)入lookupAllEventTypes(eventClass)方法,看看返回的事件類型,并且知道他存儲(chǔ)到Map集合中,即key是當(dāng)前事件class,value是該事件的所有類型,包括父類,接口等。
看看方法postSingleEventForEventType(event, postingState, clazz),發(fā)送事件
private boolean postSingleEventForEventType(Object event, PostingThreadState postingState, Class<?> eventClass) {CopyOnWriteArrayList<Subscription> subscriptions;synchronized (this) {//通過(guò)當(dāng)前的事件class,獲取訂閱事件列表subscriptions = subscriptionsByEventType.get(eventClass);}if (subscriptions != null && !subscriptions.isEmpty()) {for (Subscription subscription : subscriptions) {//對(duì)PostingThreadState進(jìn)行賦值postingState.event = event;postingState.subscription = subscription;boolean aborted = false;try {//發(fā)送事件postToSubscription(subscription, event, postingState.isMainThread);aborted = postingState.canceled;} finally {//設(shè)置參數(shù)為空postingState.event = null;postingState.subscription = null;postingState.canceled = false; //設(shè)置標(biāo)志}if (aborted) {break;}}return true;}return false;}大家是否還記得在注冊(cè)的時(shí)候出現(xiàn)的CopyOnWriteArrayList<Subscription>在這里就用到了,通過(guò)發(fā)送事件的class獲取CopyOnWriteArrayList容器里面的訂閱事件信息,包括注冊(cè)者對(duì)象,訂閱方法等。然后遍歷并進(jìn)行發(fā)送事件。在此方法發(fā)布postToSubscription()事件
/*** subscription:發(fā)布訂閱的事件處理器* event:當(dāng)前發(fā)布的事件* isMainThread:是否是在主線程中*/ private void postToSubscription(Subscription subscription, Object event, boolean isMainThread) {switch (subscription.subscriberMethod.threadMode) {case POSTING:invokeSubscriber(subscription, event);break;case MAIN:if (isMainThread) {invokeSubscriber(subscription, event);} else {mainThreadPoster.enqueue(subscription, event);}break;case MAIN_ORDERED:if (mainThreadPoster != null) {mainThreadPoster.enqueue(subscription, event);} else {// temporary: technically not correct as poster not decoupled from subscriberinvokeSubscriber(subscription, event);}break;case BACKGROUND:if (isMainThread) {backgroundPoster.enqueue(subscription, event);} else {invokeSubscriber(subscription, event);}break;case ASYNC:asyncPoster.enqueue(subscription, event);break;default:throw new IllegalStateException("Unknown thread mode: " + subscription.subscriberMethod.threadMode);}}好了,這就是之前我們?cè)谧?cè)中有一個(gè)地方遺留下的,就是判斷是否是粘性狀態(tài)是調(diào)用的方法,大家往回看,就看到了在方法checkPostStickyEventToSubscription中有調(diào)用到該方法。
這里會(huì)根據(jù),在方法中所選的threadMode進(jìn)行調(diào)用,
- 1.MAIN,如果當(dāng)前是否是UI線程,則會(huì)進(jìn)入到invokeSubscriber(subscription, event);方法中。否則將調(diào)用mainThreadPoster.enqueue(subscription, event);這個(gè)方法將交給HandlerPoster.class里面的enqueue(Subscription subscription, Object event)方法,HandlerPoster.class現(xiàn)實(shí)了該接口,移交給handle完成,大家可以進(jìn)入HandlerPoster.class看看,這里就不說(shuō)了。
- 2.POSTING直接調(diào)用 invokeSubscriber(subscription, event);
- 3.MAIN_ORDERED如果當(dāng)前mainThreadPoster不為空則調(diào)用 mainThreadPoster.enqueue(subscription, event);和MAIN進(jìn)入HandlerPoster.class,反之調(diào)用invokeSubscriber(subscription, event);
- 4.BACKGROUND如果當(dāng)前是主線程,則調(diào)用backgroundPoster.enqueue(subscription, event);,反之調(diào)用invokeSubscriber(subscription, event);
- 5.ASYNC,異步方法調(diào)用,執(zhí)行 asyncPoster.enqueue(subscription, event);,方法進(jìn)行跟蹤,該類有實(shí)現(xiàn)了Runnable接口,然后調(diào)用eventBus.invokeSubscriber(pendingPost);,最終將調(diào)用了invoke方法。
invoke()這是一個(gè)本地的方法,將調(diào)用C/C++的到方法進(jìn)行發(fā)布。最后將進(jìn)入到訂閱方法中。并傳遞該事件到到訂閱的方法中。
好了,這里我們將post發(fā)布事件的方法簡(jiǎn)單的分析了一下。整個(gè)EventBus的分析差不多完成了,但是,我們還有一點(diǎn)不能忘記就是解除綁定。接下來(lái)我們來(lái)看看解除綁定的方法。
- 注:該方法一般生命周期的onDestroy()方法中進(jìn)行解除綁定。
代碼如下:
EventBus.getDefault().unregister(this);直接進(jìn)入unregister(this)
/** Unregisters the given subscriber from all event classes. */public synchronized void unregister(Object subscriber) {List<Class<?>> subscribedTypes = typesBySubscriber.get(subscriber);if (subscribedTypes != null) {for (Class<?> eventType : subscribedTypes) {unsubscribeByEventType(subscriber, eventType);}typesBySubscriber.remove(subscriber);} else {logger.log(Level.WARNING, "Subscriber to unregister was not registered before: " + subscriber.getClass());}} /** Only updates subscriptionsByEventType, not typesBySubscriber! Caller must update typesBySubscriber. *//*** subscriber:指代當(dāng)前解除注冊(cè)的對(duì)象如Activity,* eventType:發(fā)送的事件類型,post函數(shù)的實(shí)體對(duì)象class*/ private void unsubscribeByEventType(Object subscriber, Class<?> eventType) {List<Subscription> subscriptions = subscriptionsByEventType.get(eventType);if (subscriptions != null) {int size = subscriptions.size();for (int i = 0; i < size; i++) {Subscription subscription = subscriptions.get(i);if (subscription.subscriber == subscriber) {subscription.active = false;subscriptions.remove(i); //刪除i--; //目的是減少遍歷次數(shù)size--;}}} }解除綁定,這里很簡(jiǎn)單。這里就不一一進(jìn)行解釋了,^_^。
總結(jié)
1.本篇文章主要對(duì)EventBus源碼進(jìn)行簡(jiǎn)單的分析。主要是進(jìn)行了觀察者模式的一些高級(jí)運(yùn)用。如果大家對(duì)觀察者模式理解不怎么清楚可以進(jìn)入這里看看簡(jiǎn)單的案例觀察者模式,內(nèi)容非常簡(jiǎn)單。
2.相關(guān)的EvenBut的使用,請(qǐng)看之前的內(nèi)容。如EventBus認(rèn)識(shí)(一)、EventBus的ThreadMode使用以及分析(二)等等。
3.學(xué)習(xí)本篇文章中可以認(rèn)識(shí)到一些常用的類如CopyOnWriteArrayList、ThreadLocal等,到時(shí)可以深入研究一下,有助我們提高。
4.一些編程思想,設(shè)計(jì)模式值得我們?nèi)W(xué)習(xí)的,如單例模式EventBus雙重校驗(yàn)、建造者模式,EventBus構(gòu)造器的時(shí)候用到,用了初始化各個(gè)參數(shù)等等。面向接口編程而不針對(duì)實(shí)現(xiàn)編程。
5.如果有什么問(wèn)題希望大家進(jìn)行指正,好好學(xué)習(xí),一起進(jìn)步。
總結(jié)
以上是生活随笔為你收集整理的EventBus源码分析的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 10. Python面向对象
- 下一篇: 2019年1月3日