日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【EventBus】EventBus 源码解析 ( 注册订阅者 | 订阅方法 | 查找订阅方法 )

發布時間:2025/6/17 编程问答 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【EventBus】EventBus 源码解析 ( 注册订阅者 | 订阅方法 | 查找订阅方法 ) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

  • 一、EventBus 注冊訂閱者
  • 二、訂閱方法
  • 三、查找訂閱方法 findSubscriberMethods 方法
  • 四、查找訂閱方法 findUsingInfo 方法
  • 五、查找訂閱方法 findUsingReflectionInSingleClass





一、EventBus 注冊訂閱者



EventBus 中調用 EventBus.getDefault().register(this) 注冊訂閱者 ; 該方法中主要進行了如下 222 個步驟 :

  • ① 獲取 訂閱者 集合 , 查找當前訂閱類中符合條件的訂閱方法集合 ;
  • ② 遍歷 訂閱者 集合 , 進行事件訂閱 , 保存數據 , 這些數據就是一些映射關系
/*** EventBus是Java和Android的中央發布/訂閱事件系統。* 事件被發布({@link#post(Object)})到總線,總線將其傳遞給具有匹配處理程序的訂閱者* 事件類型的方法。* 要接收事件,訂閱者必須使用{@link#register(Object)}將自己注冊到總線。* 一旦注冊,訂閱服務器將接收事件,直到調用{@link#unregister(Object)}。* 事件處理方法必須由{@link Subscribe}注釋,必須是公共的,不返回任何內容(void),* 并且只有一個參數(事件)。*/ public class EventBus {/*** 注冊給定訂閱服務器以接收事件。訂閱者一旦對接收事件不再感興趣,就必須調用{@link#unregister(Object)}。* <p/>* 訂閱服務器具有必須由{@link Subscribe}注釋的事件處理方法。* {@link Subscribe}注釋還允許類似{@link ThreadMode}和優先級的配置。*/public void register(Object subscriber) {Class<?> subscriberClass = subscriber.getClass();// 1. 獲取 訂閱者 集合 , 查找當前訂閱類中符合條件的訂閱方法集合 List<SubscriberMethod> subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass);// 2. 遍歷 訂閱者 集合 , 進行事件訂閱 , 保存數據 , 這些數據就是一些映射關系 synchronized (this) {for (SubscriberMethod subscriberMethod : subscriberMethods) {subscribe(subscriber, subscriberMethod);}}} }



二、訂閱方法



SubscriberMethod 對訂閱的方法進行了一些封裝 , 包括了方法的 Method 對象 Method method , 線程模式 ThreadMode threadMode , 事件類型 Class<?> eventType, 優先級 int priority , 粘性 boolean sticky 等 ;

/** 由EventBus內部使用并生成訂戶索引。 */ public class SubscriberMethod {final Method method;final ThreadMode threadMode;final Class<?> eventType;final int priority;final boolean sticky;/** Used for efficient comparison */String methodString; }



三、查找訂閱方法 findSubscriberMethods 方法



訂閱方法緩存機制 : 從緩存中獲取 訂閱方法 , METHOD_CACHE 緩存是一個 HashMap 集合 ;

如果訂閱者有很多方法 , 如果每次訂閱都要查詢所有的方法 , 如果遍歷一次 Activity 的所有方法 很消耗性能 ; 因此這里引入了緩存機制 ;

第一次訂閱時 , 將方法都放在緩存集合中 , 如果第二次訂閱 , 不用再次查找方法 ;


如果緩存中沒有訂閱方法 , 那么說明這是第一次查找訂閱方法 , 一般情況下都是調用 subscriberMethods = findUsingInfo(subscriberClass) 方法 , 獲取訂閱方法 ;

class SubscriberMethodFinder {// 方法緩存集合private static final Map<Class<?>, List<SubscriberMethod>> METHOD_CACHE = new ConcurrentHashMap<>();List<SubscriberMethod> findSubscriberMethods(Class<?> subscriberClass) {// 從緩存中獲取 訂閱方法 , METHOD_CACHE 緩存是一個 HashMap 集合// 如果訂閱者有很多方法 , 如果每次訂閱都要查詢所有的方法 , 很消耗性能 // 第一次訂閱時 , 將方法都放在集合中 // 如果第二次訂閱 , 不用再次查找方法List<SubscriberMethod> subscriberMethods = METHOD_CACHE.get(subscriberClass);if (subscriberMethods != null) {return subscriberMethods;}// 如果緩存中沒有訂閱方法 , 那么說明這是第一次查找訂閱方法// ignoreGeneratedIndex 屬性默認是 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;}} }

下面分析 findUsingInfo 方法 ;





四、查找訂閱方法 findUsingInfo 方法



FindState 是輔助類 , 其中進行了狀態保存等信息 ;

參數 Class<?> subscriberClass 是訂閱者類 , 將訂閱類設置到 FindState 查找狀態類對象中 ;

該方法的核心是調用了 findUsingReflectionInSingleClass(findState) 方法 , 進行后續查找操作 ;

class SubscriberMethodFinder {private List<SubscriberMethod> findUsingInfo(Class<?> subscriberClass) {// FindState 是輔助類 , 其中進行了狀態保存等信息 FindState findState = prepareFindState();// 將訂閱類設置到 FindState 查找狀態類對象中 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);} }



五、查找訂閱方法 findUsingReflectionInSingleClass



通過反射獲取訂閱者類中的所有方法 , 遍歷 訂閱者 類中的所有方法 , 過濾掉不符合條件的方法 , 將符合條件的方法封裝到 findState.subscriberMethods 集合中 ;

過濾方案 :

  • 訂閱方法的參數個數肯定只有 1 個 ;
  • 訂閱方法上有 @Subscribe 注解 ;
  • @Subscribe 注解屬性判斷 ;
  • @Subscribe 注解線程模式判斷 ;
class SubscriberMethodFinder {private void findUsingReflectionInSingleClass(FindState findState) {Method[] methods;try {// 通過反射獲取訂閱者類中的所有方法 // 這比getMethods快,特別是當訂閱者是像 Activity 這樣的大類時methods = findState.clazz.getDeclaredMethods();} catch (Throwable th) {}// 遍歷 訂閱者 類中的所有方法 , 過濾掉不符合條件的方法 , for (Method method : methods) {int modifiers = method.getModifiers();if ((modifiers & Modifier.PUBLIC) != 0 && (modifiers & MODIFIERS_IGNORE) == 0) {Class<?>[] parameterTypes = method.getParameterTypes();// 訂閱方法的參數個數肯定只有 1 個if (parameterTypes.length == 1) {// 訂閱方法上有 @Subscribe 注解 Subscribe subscribeAnnotation = method.getAnnotation(Subscribe.class);if (subscribeAnnotation != null) {// @Subscribe 注解屬性判斷 Class<?> eventType = parameterTypes[0];if (findState.checkAdd(method, eventType)) {// @Subscribe 注解線程模式判斷ThreadMode threadMode = subscribeAnnotation.threadMode();// 將符合條件的方法封裝到 findState.subscriberMethods 集合中 ; findState.subscriberMethods.add(new SubscriberMethod(method, eventType, threadMode,subscribeAnnotation.priority(), subscribeAnnotation.sticky()));}}} } }} }

總結

以上是生活随笔為你收集整理的【EventBus】EventBus 源码解析 ( 注册订阅者 | 订阅方法 | 查找订阅方法 )的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。