使用上比較簡單,就是注冊和解注冊以及發(fā)送事件辩越,外加一個(gè)黏性事件。
注冊
注冊主要是將當(dāng)前Activity對象傳進(jìn)去信粮,然后拿到對應(yīng)的class黔攒;
反射拿到所有的方法,然后對方法進(jìn)行過濾强缘;需要有對應(yīng)的注解督惰,需要是public方法,需要是只有一個(gè)參數(shù)欺旧;
這中間入股需要追溯父類和接口姑丑,則需要去當(dāng)前類的父類中去找對應(yīng)的符合條件的方法,同時(shí)對參數(shù)的父類以及接口也有涉獵辞友。
組裝方法類栅哀,包括在什么線程執(zhí)行,優(yōu)先級等称龙;
拿到當(dāng)前類所有符合條件的組合方法后留拾,執(zhí)行訂閱;
在訂閱中鲫尊,存在一個(gè)全局MAP痴柔,就是按照類型參數(shù)為key,當(dāng)前類class和組合方法再組合的類組成的List作為value(一般接受事件會在多個(gè)Activity中都有涉獵)疫向,形成一個(gè)全局的大列表咳蔚,保存起來豪嚎。
如果在注冊之前有黏性事件發(fā)送,則在注冊后就立即執(zhí)行之前的黏性事件谈火。
發(fā)送事件
從大列表中侈询,根據(jù)參數(shù)類型找到對應(yīng)的再組合List,然后在指定的線程中反射執(zhí)行糯耍。
黏性事件發(fā)送就是在發(fā)送事件的基礎(chǔ)上增加一個(gè)List記錄一下扔字,這樣在別的Activity中注冊時(shí)會檢測是否有需要執(zhí)行的黏性事件,直接執(zhí)行温技,執(zhí)行完移除記錄革为。List中存儲的始終是未執(zhí)行的。
解注冊
沒什么好說的舵鳞,從對應(yīng)的列表中移除震檩。
索引
之前的操作都是在注冊時(shí)反射操作,于性能上有損耗蜓堕;索引是在編譯期提前生成代碼恳蹲。需要增阿基注解處理器,注解處理器去生成俩滥,使用規(guī)則就是在初始化時(shí)增加索引嘉蕾;索引里面描述方法組合信息,這樣就不用速反射查找了霜旧,提前自己查找好错忱,然后添加進(jìn)去,把反射的工作用手動替代了挂据。
從性能上來說是提升了一點(diǎn)以清,但是從代碼維護(hù)和編寫上來說,累崎逃。
事件傳遞性
接收事件的class
- 當(dāng)前類中
- 事件參數(shù)類型都會接收
- 事件參數(shù)類型的父類也都會接收
- 當(dāng)前類父類中
- 事件參數(shù)類型都會接收
- 事件參數(shù)類型的父類也都會接收
還有一個(gè)不太靠譜的東西掷倔,就是當(dāng)前類AA的父類A中,存在同名方法event,且方法參數(shù)類型都是發(fā)送類型个绍;這種情況下勒葱,最多有一個(gè),超過一個(gè)就報(bào)錯(cuò)巴柿。
當(dāng)前類AA凛虽,父類A;
事件XX广恢,父類X;
AA中的事件eventAA1(XX),eventAA2(XX);
A中的事件eventAA1(XX),eventAA2(XX);
發(fā)送事件post(XX)
上面父類A中有兩個(gè)同名方法凯旋,就掛了,最多允許一個(gè);XX換成X至非,也是如此钠署。
真不靠譜,有啥意義呢荒椭?
2021-11-24補(bǔ)充
幾個(gè)集合
private static final Map<Class<?>, List<Class<?>>> eventTypesCache = new HashMap<>();
private final Map<Class<?>, CopyOnWriteArrayList<Subscription>> subscriptionsByEventType;
private final Map<Object, List<Class<?>>> typesBySubscriber;
private final Map<Class<?>, Object> stickyEvents;
一共四個(gè)集合踏幻;
第一個(gè)集合的用處和作用:
用處:
用于發(fā)射事件類型的繼承性,如果要考慮繼承性戳杀,會將事件類型的Class以及對應(yīng)的父類Class,接口Class一直往上追溯夭苗,組裝成一個(gè)Class列表作為value信卡,然后以該事件類型的Class作為key。
作用:
在發(fā)射對應(yīng)的事件時(shí)题造,如果考慮事件繼承傍菇,則會把該事件對應(yīng)的所有父類以及接口類Class都找出來,然后在另一個(gè)集合中(上面第二個(gè)集合)去查找已經(jīng)注冊過得“宿主”界赔,然后執(zhí)行丢习。
第二個(gè)集合的用處和作用
用處:
“宿主”里面會有起碼一個(gè)的注解事件方法,這里將注解事件方法拆分淮悼,拿到所有的信息(方法Method咐低,執(zhí)行線程,事件參數(shù)類型袜腥,優(yōu)先級见擦,黏性標(biāo)簽)組裝成一個(gè)方法信息承載類SubscriberMethod,然后再組裝一個(gè)“宿主-方法”信息承載類羹令,里面包括“宿主”和SubscriberMethod鲤屡,這個(gè)“宿主-方法”信息承載類就是Subscription;
一個(gè)事件類型可能會有多個(gè)“宿主”注冊福侈,這里以事件Class為key酒来,Subscription組成的List為value。
作用:
在注冊階段收集肪凛,一是可以防止重復(fù)注冊堰汉;而且在初測階段就根據(jù)優(yōu)先級排好了序;
再一個(gè)就是在時(shí)間發(fā)送時(shí)伟墙,根據(jù)事件Class找到所有注冊過的方法衡奥,然后去反射執(zhí)行。
延伸:
和第一個(gè)集合配合远荠,就是第一個(gè)集合找到父類以及父接口等所有可追溯的Class矮固,然后在這個(gè)集合中去查找對應(yīng)搜集的方法。
第三個(gè)集合的作用和用處
用處:
以“宿主”為key,宿主里面的所有注冊事件類型的Class組成的List為value档址。
作用:
在注冊時(shí)搜集盹兢。
因?yàn)槭且浴八拗鳌睘閗ey的,所以可以對外提供方法守伸,判斷該宿主是否已經(jīng)注冊绎秒;
在解注冊時(shí),是要釋放一個(gè)宿主尼摹,于是就根據(jù)當(dāng)前“宿主”找到所有注冊事件類型见芹;找到了事件的類型,就到了第一個(gè)和第二個(gè)集合以事件類型為key的主場蠢涝;第二個(gè)集合直接根據(jù)事件類型玄呛,找到對應(yīng)的“宿主-方法”信息承載體,直接移除和二;
第一個(gè)集合啥都沒做徘铝,為什么呢?因?yàn)闆]必要惯吕;首先解注冊時(shí)釋放的是“宿主”惕它,而不是一個(gè)事件類型,所以該“宿主”里面注冊的事件類型在別的地方可能也會用到废登;第二個(gè)就是這個(gè)事件類型對應(yīng)的列表是一個(gè)緩存淹魄,下次進(jìn)來或者別的頁面也存在該事件類型的地方還會復(fù)用。所以釋放意義不大堡距。
另外他的作用是在發(fā)射事件的時(shí)候體現(xiàn)出來揭北,他會遍歷事件類型的父類以及接口等往上追溯的Class,對應(yīng)的“宿主-方法”吏颖,然后去執(zhí)行搔体,但是查找需要第二個(gè)集合的幫忙,而第二個(gè)集合解注冊時(shí)已經(jīng)移除了半醉,所以也不會有事件去響應(yīng)疚俱。
第四個(gè)集合的作用和用處
用處:
用來手機(jī)黏性事件,事件參數(shù)Class為key缩多,事件參數(shù)為value呆奕。
作用:
發(fā)射的時(shí)候搜集。
在“黏性宿主”注冊時(shí)衬吆,去列表取出執(zhí)行梁钾。
如果黏性事件類型有子類,則子類也會響應(yīng)逊抡;但是這里不是自己去追溯子類姆泻,而是確實(shí)發(fā)射過子類的粘性事件并存儲在該列表中零酪。
上面那個(gè)子類做個(gè)解釋,他不是直接去響應(yīng)子類的方法拇勃;比如發(fā)射一個(gè)子類事件和父類事件四苇,在”宿主“初始化注冊時(shí),如果注冊了父類方法方咆,則兩個(gè)黏性事件都會在父類方法中標(biāo)執(zhí)行月腋。
發(fā)送一個(gè)父類型,一個(gè)子類型瓣赂,最終父事件中會執(zhí)行父類型和子類型榆骚,子事件中只會執(zhí)行子事件
所以黏性事件的這種機(jī)制還蠻奇怪的。
延伸:
并沒有看到黏性事件的移除煌集,也就意味著妓肢,這個(gè)黏性事件在執(zhí)行后仍然會再次執(zhí)行