SubscriberMethodFinder類
SubscriberMethodFinder
大體就是去注冊后對應的方法
其中宝惰,屬性
private static final int BRIDGE = 0x40;
有對應的說明:
In newer class files, compilers may add methods. Those are called bridge or synthetic methods.
EventBus must ignore both. There modifiers are not public but defined in the Java class file format:
http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.6-200-A.1
自己也沒有研究過jvm,簡單貼一下圖
下面對應的變量修飾符
private static final int MODIFIERS_IGNORE = Modifier.ABSTRACT | Modifier.STATIC | BRIDGE | SYNTHETIC;
也就是粱腻,
方法上的注解庇配,會忽略這幾種修飾符的方法
屬性方面
先重點看一下這2個容器
一個是 : 本類存儲的容器類,用于 查找 和 存儲
另一個是 :傳入的引用
方法大體了解
這里绍些,我們可以發(fā)現捞慌,
除了 構造 和 findSubscriberMethods方法 是 public對外的
其他,都是 private 的
也就是柬批,我們主要認識 findSubscriberMethods方法 即可
和EventBus 2.4 對比
我們大體可以猜測啸澡,其他多余出來的方法,都是用于判斷反射的
findSubscriberMethods方法
先一起大體過一下
List<SubscriberMethod> findSubscriberMethods(Class<?> subscriberClass) {
List<SubscriberMethod> subscriberMethods = METHOD_CACHE.get(subscriberClass);
if (subscriberMethods != null) {
return subscriberMethods;
}
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;
}
}
這里氮帐,大體就是
- 如果有Map緩存中有值嗅虏,就直接獲取
- 如果 ignoreGeneratedIndex為true 就 findUsingReflection(subscriberClass) 通過反射獲取
- 如果 ignoreGeneratedIndex為false ,就 findUsingInfo(subscriberClass) 獲取
- 最后
- subscriberMethods 為空上沐,內部報異常(對外是不會提示的)
- subscriberMethods 不空皮服,把對應的key為 subscriberClass, value為subscriberMethods 加入到 Map緩存中
findUsingInfo方法
上面提到的
如果Map緩存中 沒有值,并且 ignoreGeneratedIndex為false的時候
會調用這個方法
具體看下源碼
private List<SubscriberMethod> findUsingInfo(Class<?> subscriberClass) {
FindState findState = prepareFindState();
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);
}
這里通過 prepareFindState()冰更, 獲取 FindState 對象
(具體方法产徊,見下面的方法說明)
FindState 靜態(tài)內部類
這里因為上面的方法會獲取這個對象
所以,我們先來看一下這個對象
static class FindState {
final List<SubscriberMethod> subscriberMethods = new ArrayList<>();
final Map<Class, Object> anyMethodByEventType = new HashMap<>();
final Map<String, Class> subscriberClassByMethodKey = new HashMap<>();
final StringBuilder methodKeyBuilder = new StringBuilder(128);
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;
}
boolean checkAdd(Method method, Class<?> 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 {
if (existing instanceof Method) {
if (!checkAddWithMethodSignature((Method) existing, eventType)) {
// Paranoia check
throw new IllegalStateException();
}
// Put any non-Method object to "consume" the existing Method
anyMethodByEventType.put(eventType, this);
}
return checkAddWithMethodSignature(method, eventType);
}
}
private boolean checkAddWithMethodSignature(Method method, Class<?> eventType) {
methodKeyBuilder.setLength(0);
methodKeyBuilder.append(method.getName());
methodKeyBuilder.append('>').append(eventType.getName());
String methodKey = methodKeyBuilder.toString();
Class<?> methodClass = method.getDeclaringClass();
Class<?> methodClassOld = subscriberClassByMethodKey.put(methodKey, methodClass);
if (methodClassOld == null || methodClassOld.isAssignableFrom(methodClass)) {
// Only add if not already found in a sub class
return true;
} else {
// Revert the put, old class is further down the class hierarchy
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;
}
}
}
}
這個代碼比較長蜀细,我們大體看一下即可
- initForSubscriber方法
- 初始化靜態(tài)內部類
- 傳遞 Class<?> 對象
- 設置 SubscriberInfo 為空
- recycle方法
- 所有集合都 clear 舟铜, 引用對象都設置為null
- 因為是靜態(tài)的, 所以 回收后再次調用
- checkAdd方法
- boolean類型
- 將對應的 key 為 eventType奠衔, value 為 Method 放入到 Map中
- 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.
- 這里有2次check谆刨, 第一次check是比較快, 第二次會再次check归斤,通常一個subscriber不會監(jiān)聽2個相同的event
- checkAddWithMethodSignature方法
- 也就是第二次check痊夭,通過拼接一個string來作為一個key
- moveToSuperclass方法
- 如果 skipSuperClasses為true,或者 Superclass的startsWith對應的時候脏里,設置 clazz = null
- 其他時候她我,返回 clazz = clazz.getSuperclass().getName()
大體就是
- 初始化對應的類屬性
- 再就是check是否已經add過了(這里是2次check)
- 把class的屬性,設置為Super的class(特殊情況設置為null)
prepareFindState方法
這里是前面 findUsingInfo方法 中用到的
也就是用來獲取FindState對象的方法
private FindState prepareFindState() {
synchronized (FIND_STATE_POOL) {
for (int i = 0; i < POOL_SIZE; i++) {
FindState state = FIND_STATE_POOL[i];
if (state != null) {
FIND_STATE_POOL[i] = null;
return state;
}
}
}
return new FindState();
}
這里迫横,知道這里有一個 FIND_STATE_POOL 對象池
對象個數 POOL_SIZE 為 4
具體對象為 FindState
是一個 靜態(tài)內部類
for循環(huán)取值:
- 如果不為空番舆, 則找到對象池中 一個不為空的對象
- 如果為空,就返回一個新的 FindState對象()
getMethodsAndRelease 方法
先看一下源碼
private List<SubscriberMethod> getMethodsAndRelease(FindState findState) {
List<SubscriberMethod> subscriberMethods = new ArrayList<>(findState.subscriberMethods);
findState.recycle();
synchronized (FIND_STATE_POOL) {
for (int i = 0; i < POOL_SIZE; i++) {
if (FIND_STATE_POOL[i] == null) {
FIND_STATE_POOL[i] = findState;
break;
}
}
}
return subscriberMethods;
}
這里大體就是獲取 FindState中的List<SubscriberMethod>類型的對象subscriberMethods
將對應的FindState對象放入對象池中
最后返回List<SubscriberMethod>的值
getSubscriberInfo方法
也先看一下源碼
private SubscriberInfo getSubscriberInfo(FindState findState) {
if (findState.subscriberInfo != null && findState.subscriberInfo.getSuperSubscriberInfo() != null) {
SubscriberInfo superclassInfo = findState.subscriberInfo.getSuperSubscriberInfo();
if (findState.clazz == superclassInfo.getSubscriberClass()) {
return superclassInfo;
}
}
if (subscriberInfoIndexes != null) {
for (SubscriberInfoIndex index : subscriberInfoIndexes) {
SubscriberInfo info = index.getSubscriberInfo(findState.clazz);
if (info != null) {
return info;
}
}
}
return null;
}
也就是如果傳入的findState對象不空矾踱,并且有SubscriberInfo的值
(這塊自己感覺沒有賦值的地方恨狈,應該為null,具體先不糾結)
或者對應的值呛讲,并且SubscriberInfo不為空禾怠,Class相同的時候,
返回對應的SubscriberInfo對象
如果上面不符合贝搁,會取從構造傳進來的subscriberInfoIndexes對象中
for循環(huán)吗氏,獲取第一個 SubscriberInfo 對象
findUsingReflection方法
這里就不貼代碼了
大體為:
- 先通過 prepareFindState方法,獲得內部靜態(tài)類的FindState對象
- 再while (findState.clazz != null)循環(huán)
- 通過findUsingReflectionInSingleClass方法
- 每次獲取一個類后雷逆,通過 FindState的moveToSuperclass()方法牲证,設置class引用
- 如果有父類,設置為class=class.getSuperclass()
- 如果沒有父類关面,賦值class=null坦袍,從而讓findUsingReflection中,離開while循環(huán)
findUsingReflectionInSingleClass方法
上面用到的
大體為:
- 獲取每個SingleClass的方法等太,
- 在除去其他修飾的方法后捂齐,獲取 注解的 Subscribe對象,
- 放入FindState對象的subscriberMethods容器中
簡單總結
對外缩抡,就2個方法
- 一個是構造奠宜,傳入 List<SubscriberInfoIndex> subscriberInfoIndexes 等變量
- 一個是 findSubscriberMethods, 去找對應的注冊者Subscriber的方法
對應的方法,會存入
Map<Class<?>, List<SubscriberMethod>> METHOD_CACHE = new ConcurrentHashMap<>()
容器中
- 如果容器中有压真,會從容器中獲取 List<SubscriberMethod>
- 如果容器中沒有
- ignoreGeneratedIndex 為 true娩嚼,則通過反射去拿具體的類中獲取
- ignoreGeneratedIndex 為 false,則 通過 findUsingInfo方法獲取
- FindState對象池中滴肿,獲取對象
- 通過while循環(huán)(這里后面的方法會設置對象岳悟,確定可以跳出循環(huán))
- 遍歷,獲取 List<SubscriberMethod> 對象
- 如果FindState 對象池 中有泼差,則直接獲取
- 如果 FindState 對象池中沒有贵少,則 從構造傳入的subscriberInfoIndexes對象中獲取
- 其實,最終也就獲取 List<SubscriberMethod>
- 通過傳進來的Class<?> 對象
- 也就是在 Activity或者Fragment中注冊的Class
- 獲取@Subscriber 進行注解的方法 們
(其實堆缘,自己不太理解滔灶,這里為什么用一個容器存儲,為什么要這樣寫結構 等等吼肥,只是簡單的敘述了下流程录平,等有時間,再考慮一下)