【EventBus】事件通信框架 ( 订阅方法注册 | 注册 事件类型 - 订阅类 + 订阅方法 到指定集合 | 取消注册 数据准备 )
文章目錄
- 一、注冊(cè)訂閱方法
- 二、完整代碼示例
一、注冊(cè)訂閱方法
訂閱方法注冊(cè)的過(guò)程就是將 訂閱方法參數(shù)類型 和 訂閱類 + 訂閱方法 封裝類 , 保存到 Map<Class<?>, CopyOnWriteArrayList<MySubscription>> subscriptionsByEventType 集合中 , 該集合的鍵值含義如下 :
- Key - 訂閱者方法事件參數(shù)類型
- Value - 封裝 訂閱者對(duì)象 與 訂閱方法 的 MySubscription 集合
同時(shí) , 還要為 取消注冊(cè) 準(zhǔn)備數(shù)據(jù) , 取消注冊(cè)數(shù)據(jù)存放在 Map<Object, List<Class<?>>> typesBySubscriber 集合中 , 該集合的鍵值含義如下 :
- Key - 訂閱者對(duì)象
- Value - 訂閱者方法參數(shù)集合
1. 獲取事件類型 : 獲取訂閱方法接收的參數(shù)類型 ;
// 獲取訂閱方法接收的參數(shù)類型Class<?> eventType = subscriberMethod.getEventType();2. 獲取訂閱者 : 獲取 Map<Class<?>, CopyOnWriteArrayList<MySubscription>> subscriptionsByEventType 集合中 eventType 參數(shù)類型對(duì)應(yīng)的 訂閱者封裝類 ( 封裝 訂閱者對(duì)象 + 訂閱方法 ) 集合 ;
// 獲取 eventType 參數(shù)類型對(duì)應(yīng)的 訂閱者封裝類 ( 封裝 訂閱者對(duì)象 + 訂閱方法 ) 集合CopyOnWriteArrayList<MySubscription> subscriptions =subscriptionsByEventType.get(eventType);3. 訂閱者為空處理 : 如果獲取的集合為空 , 說(shuō)明 eventType 參數(shù)對(duì)應(yīng)的訂閱方法一個(gè)也沒有注冊(cè)過(guò) , 這里先創(chuàng)建一個(gè)集合 , 放到 subscriptionsByEventType 鍵值對(duì)中 ;
// 如果獲取的集合為空 , 說(shuō)明 eventType 參數(shù)對(duì)應(yīng)的訂閱方法一個(gè)也沒有注冊(cè)過(guò)// 這里先創(chuàng)建一個(gè)集合 , 放到 subscriptionsByEventType 鍵值對(duì)中if (subscriptions == null) {// 創(chuàng)建集合subscriptions = new CopyOnWriteArrayList<>();// 將集合設(shè)置到 subscriptionsByEventType 鍵值對(duì)集合中subscriptionsByEventType.put(eventType, subscriptions);}4. 設(shè)置訂閱者集合 : 封裝 訂閱者對(duì)象 + 訂閱方法 對(duì)象 , 將創(chuàng)建的 訂閱者對(duì)象 + 訂閱方法 對(duì)象 添加到 CopyOnWriteArrayList 集合中 ;
// 封裝 訂閱者對(duì)象 + 訂閱方法 對(duì)象MySubscription subscription = new MySubscription(subscriber, subscriberMethod);// 將創(chuàng)建的 訂閱者對(duì)象 + 訂閱方法 對(duì)象 添加到 CopyOnWriteArrayList 集合中subscriptions.add(subscription);5. 設(shè)置取消注冊(cè)數(shù)據(jù) : Map<Object, List<Class<?>>> typesBySubscriber 集合用于取消注冊(cè)時(shí) , 通過(guò)訂閱者對(duì)象 查找 該訂閱者對(duì)象中所有訂閱方法的 事件參數(shù)類型 集合 , 然后通過(guò)事件類型 , 就可以去 Map<Class<?>, CopyOnWriteArrayList<MySubscription>> subscriptionsByEventType 集合中查找相關(guān)數(shù)據(jù) ;
// 為取消注冊(cè)準(zhǔn)備數(shù)據(jù)// 設(shè)置 Map<Object, List<Class<?>>> typesBySubscriberList<Class<?>> eventTypes = typesBySubscriber.get(subscriber);if (eventTypes == null) {// 創(chuàng)建新的集合, 用于存放訂閱方法的參數(shù)類型eventTypes = new ArrayList<>();// 將新的集合設(shè)置到 Map<Object, List<Class<?>>> typesBySubscriber 集合中typesBySubscriber.put(subscriber, eventTypes);}// 將新的 訂閱方法類型 放入到集合中eventTypes.add(eventType);部分代碼示例 :
/*** 方法訂閱* 將 訂閱方法參數(shù)類型 和 訂閱類 + 訂閱方法 封裝類 , 保存到* Map<Class<?>, CopyOnWriteArrayList<MySubscription>> subscriptionsByEventType 集合中* Key - 訂閱者方法事件參數(shù)類型* Value - 封裝 訂閱者對(duì)象 與 訂閱方法 的 MySubscription 集合** 取消注冊(cè)數(shù)據(jù)準(zhǔn)備* 取消注冊(cè)數(shù)據(jù)存放在 Map<Object, List<Class<?>>> typesBySubscriber 集合中* Key - 訂閱者對(duì)象* Value - 訂閱者方法參數(shù)集合** @param subscriber 訂閱者對(duì)象* @param subscriberMethod 訂閱方法*/private void subscribe(Object subscriber, MySubscriberMethod subscriberMethod) {// 獲取訂閱方法接收的參數(shù)類型Class<?> eventType = subscriberMethod.getEventType();// 獲取 eventType 參數(shù)類型對(duì)應(yīng)的 訂閱者封裝類 ( 封裝 訂閱者對(duì)象 + 訂閱方法 ) 集合CopyOnWriteArrayList<MySubscription> subscriptions =subscriptionsByEventType.get(eventType);// 如果獲取的集合為空 , 說(shuō)明 eventType 參數(shù)對(duì)應(yīng)的訂閱方法一個(gè)也沒有注冊(cè)過(guò)// 這里先創(chuàng)建一個(gè)集合 , 放到 subscriptionsByEventType 鍵值對(duì)中if (subscriptions == null) {// 創(chuàng)建集合subscriptions = new CopyOnWriteArrayList<>();// 將集合設(shè)置到 subscriptionsByEventType 鍵值對(duì)集合中subscriptionsByEventType.put(eventType, subscriptions);}// 封裝 訂閱者對(duì)象 + 訂閱方法 對(duì)象MySubscription subscription = new MySubscription(subscriber, subscriberMethod);// 將創(chuàng)建的 訂閱者對(duì)象 + 訂閱方法 對(duì)象 添加到 CopyOnWriteArrayList 集合中subscriptions.add(subscription);// 為取消注冊(cè)準(zhǔn)備數(shù)據(jù)// 設(shè)置 Map<Object, List<Class<?>>> typesBySubscriberList<Class<?>> eventTypes = typesBySubscriber.get(subscriber);if (eventTypes == null) {// 創(chuàng)建新的集合, 用于存放訂閱方法的參數(shù)類型eventTypes = new ArrayList<>();// 將新的集合設(shè)置到 Map<Object, List<Class<?>>> typesBySubscriber 集合中typesBySubscriber.put(subscriber, eventTypes);}// 將新的 訂閱方法類型 放入到集合中eventTypes.add(eventType);}二、完整代碼示例
完整代碼示例 :
package com.eventbus_demo.myeventbus;import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.CopyOnWriteArrayList;public class MyEventBus {/*** 方法緩存* Key - 訂閱類類型* Value - 訂閱方法 MySubscriberMethod 的集合* 取名與 EventBus 一致*/private static final Map<Class<?>, List<MySubscriberMethod>> METHOD_CACHE = new HashMap<>();/*** 解除注冊(cè)時(shí)使用* Key - 訂閱者對(duì)象* Value - 訂閱者對(duì)象中所有的訂閱方法的事件參數(shù)類型集合** 根據(jù)該訂閱者對(duì)象 , 查找所有訂閱方法的事件參數(shù)類型 , 然后再到 METHOD_CACHE 中 ,* 根據(jù)事件參數(shù)類型 , 查找對(duì)應(yīng)的 MySubscriberMethod 集合* MySubscriberMethod 中封裝 訂閱者對(duì)象 + 訂閱方法**/private final Map<Object, List<Class<?>>> typesBySubscriber;/*** Key - 訂閱者方法事件參數(shù)類型* Value - 封裝 訂閱者對(duì)象 與 訂閱方法 的 MySubscription 集合* 在構(gòu)造函數(shù)中初始化* CopyOnWriteArrayList 在寫入數(shù)據(jù)時(shí)會(huì)拷貝一個(gè)副本 ,* 寫完之后 , 將引用指向新的副本 ,* 該集合的線程安全級(jí)別很高*/private final Map<Class<?>, CopyOnWriteArrayList<MySubscription>> subscriptionsByEventType;/*** 全局單例*/private static MyEventBus instance;private MyEventBus() {subscriptionsByEventType = new HashMap<>();typesBySubscriber = new HashMap<>();}public static MyEventBus getInstance() {if (instance == null) {instance = new MyEventBus();}return instance;}/*** 注冊(cè)訂閱者* @param subscriber*/public void register(Object subscriber) {// 獲取訂閱者所屬類Class<?> clazz = subscriber.getClass();// 查找訂閱方法List<MySubscriberMethod> subscriberMethods = findSubscriberMethods(clazz);// 遍歷所有訂閱方法 , 進(jìn)行訂閱// 首先確保查找到的訂閱方法不為空 , 并且個(gè)數(shù)大于等于 1 個(gè)if (subscriberMethods != null && !subscriberMethods.isEmpty()) {for (MySubscriberMethod method : subscriberMethods) {// 正式進(jìn)行訂閱subscribe(subscriber, method);}}}/*** 方法訂閱* 將 訂閱方法參數(shù)類型 和 訂閱類 + 訂閱方法 封裝類 , 保存到* Map<Class<?>, CopyOnWriteArrayList<MySubscription>> subscriptionsByEventType 集合中* Key - 訂閱者方法事件參數(shù)類型* Value - 封裝 訂閱者對(duì)象 與 訂閱方法 的 MySubscription 集合** 取消注冊(cè)數(shù)據(jù)準(zhǔn)備* 取消注冊(cè)數(shù)據(jù)存放在 Map<Object, List<Class<?>>> typesBySubscriber 集合中* Key - 訂閱者對(duì)象* Value - 訂閱者方法參數(shù)集合** @param subscriber 訂閱者對(duì)象* @param subscriberMethod 訂閱方法*/private void subscribe(Object subscriber, MySubscriberMethod subscriberMethod) {// 獲取訂閱方法接收的參數(shù)類型Class<?> eventType = subscriberMethod.getEventType();// 獲取 eventType 參數(shù)類型對(duì)應(yīng)的 訂閱者封裝類 ( 封裝 訂閱者對(duì)象 + 訂閱方法 ) 集合CopyOnWriteArrayList<MySubscription> subscriptions =subscriptionsByEventType.get(eventType);// 如果獲取的集合為空 , 說(shuō)明 eventType 參數(shù)對(duì)應(yīng)的訂閱方法一個(gè)也沒有注冊(cè)過(guò)// 這里先創(chuàng)建一個(gè)集合 , 放到 subscriptionsByEventType 鍵值對(duì)中if (subscriptions == null) {// 創(chuàng)建集合subscriptions = new CopyOnWriteArrayList<>();// 將集合設(shè)置到 subscriptionsByEventType 鍵值對(duì)集合中subscriptionsByEventType.put(eventType, subscriptions);}// 封裝 訂閱者對(duì)象 + 訂閱方法 對(duì)象MySubscription subscription = new MySubscription(subscriber, subscriberMethod);// 將創(chuàng)建的 訂閱者對(duì)象 + 訂閱方法 對(duì)象 添加到 CopyOnWriteArrayList 集合中subscriptions.add(subscription);// 為取消注冊(cè)準(zhǔn)備數(shù)據(jù)// 設(shè)置 Map<Object, List<Class<?>>> typesBySubscriberList<Class<?>> eventTypes = typesBySubscriber.get(subscriber);if (eventTypes == null) {// 創(chuàng)建新的集合, 用于存放訂閱方法的參數(shù)類型eventTypes = new ArrayList<>();// 將新的集合設(shè)置到 Map<Object, List<Class<?>>> typesBySubscriber 集合中typesBySubscriber.put(subscriber, eventTypes);}// 將新的 訂閱方法類型 放入到集合中eventTypes.add(eventType);}/*** 根據(jù)訂閱方法的事件參數(shù)查找訂閱方法* @param subscriberClass 訂閱者對(duì)象的類型* @return*/private List<MySubscriberMethod> findSubscriberMethods(Class<?> subscriberClass) {// 獲取 Class<?> clazz 參數(shù)類型對(duì)應(yīng)的 訂閱者封裝類List<MySubscriberMethod> subscriberMethods = METHOD_CACHE.get(subscriberClass);// 此處后期重構(gòu), 減少縮進(jìn)if (subscriberMethods == null) {// 說(shuō)明是首次獲取 , 初始化 METHOD_CACHE 緩存// 反射獲取 Class<?> subscriberClass 中的所有訂閱方法subscriberMethods = findByReflection(subscriberClass);if (! subscriberMethods.isEmpty()) {METHOD_CACHE.put(subscriberClass, subscriberMethods);}} else {// 如果當(dāng)前不是第一次獲取, 則直接返回從 METHOD_CACHE 緩存中獲取的 訂閱者封裝類 集合return subscriberMethods;}// 該分支走不到return null;}/*** 通過(guò)反射獲取 Class<?> subscriberClass 訂閱方法* @param subscriberClass 訂閱類* @return*/private List<MySubscriberMethod> findByReflection(Class<?> subscriberClass) {// 要返回的 MySubscriberMethod 集合List<MySubscriberMethod> subscriberMethods = new ArrayList<>();// 通過(guò)反射獲取所有帶 @MySubscribe 注解的方法Method[] methods = subscriberClass.getMethods();// 遍歷所有的方法 , 查找注解for (Method method : methods) {// 獲取方法修飾符int modifiers = method.getModifiers();// 獲取方法參數(shù)Class<?>[] params = method.getParameterTypes();// 確保修飾符必須是 public , 參數(shù)長(zhǎng)度必須是 1if (modifiers == Modifier.PUBLIC && params.length == 1) {// 獲取 MySubscribe 注解MySubscribe annotation = method.getAnnotation(MySubscribe.class);// 獲取注解不為空if (annotation != null) {// 獲取線程模式MyThreadMode threadMode = annotation.threadMode();// 此時(shí)已經(jīng)完全確定該方法是一個(gè)訂閱方法 , 直接進(jìn)行封裝MySubscriberMethod subscriberMethod = new MySubscriberMethod(method, // 方法對(duì)象threadMode, // 線程模式params[0] // 事件參數(shù));// 加入到返回集合中subscriberMethods.add(subscriberMethod);}}}return subscriberMethods;}}總結(jié)
以上是生活随笔為你收集整理的【EventBus】事件通信框架 ( 订阅方法注册 | 注册 事件类型 - 订阅类 + 订阅方法 到指定集合 | 取消注册 数据准备 )的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 【EventBus】事件通信框架 ( 订
- 下一篇: 【Android 异步操作】Androi