您的位置:首页 > 其它

EventBus源码解析02-订阅者注册

2017-08-25 07:21 381 查看
接着,我们来看EventBus的订阅过程

public void register(Object subscriber) {
Class<?> subscriberClass = subscriber.getClass();
List<SubscriberMethod> subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass);
synchronized (this) {
for (SubscriberMethod subscriberMethod : subscriberMethods) {
subscribe(subscriber, subscriberMethod);
}
}
}


这里,首先获取订阅者的class,接着,通过
subscriberMethodFinder.findSubscriberMethods
来查找订阅者的方法。

List<SubscriberMethod> findSubscriberMethods(Class<?> subscriberClass) {
//从缓存中获取
List<SubscriberMethod> subscriberMethods = METHOD_CACHE.get(subscriberClass);
if (subscriberMethods != null) {
return subscriberMethods;
}

//ignoreGenerateIndex为true会优先使用编译时Index来查找,为false将忽略使用Index来查找
if (ignoreGeneratedIndex) {
//通过反射来获取方法集合
subscriberMethods = findUsingReflection(subscriberClass);
} else {
//优先通过Index来获取方法集合
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;
}
}


一般通过
getDefault()
获取的EventBus对象,builder构建是ignoreGenerateIndex为false,故会调用
findUsingInfo()


private List<SubscriberMethod> findUsingInfo(Class<?> subscriberClass) {
//从缓存数组中获取(如果存在的话,不存在的话将新new一个)
FindState findState = prepareFindState();
//将findstate的subscriberClass和clazz变量赋值为subscriberClass
findState.initForSubscriber(subscriberClass);
while (findState.clazz != null) {
//从Index中获取subscriberInfo
findState.subscriberInfo = getSubscriberInfo(findState);
如果subscriberInfo存在
if (findState.subscriberInfo != null) {
SubscriberMethod[] array = findState.subscriberInfo.getSubscriberMethods();
for (SubscriberMethod subscriberMethod : array) {
if (findState.checkAdd(subscriberMethod.method, subscriberMethod.eventType)) {
//将符合条件的方法添加到findState的集合中
findState.subscriberMethods.add(subscriberMethod);
}
}
} else {
//说明Index中不存在,通过反射来查找Method
findUsingReflectionInSingleClass(findState);
}
//移动到父类继续查找
findState.moveToSuperclass();
}
return getMethodsAndRelease(findState);
}


findUsingInfo
中,会先从Inex中查找Method,如果Index中不存在,则通过反射来查找,最终会添加到findState的subscriberMethods集合中并返回。

再来看下
findUsingReflectionInSingleClass
,可以看到,主要就是通过反射遍历所有的Method,找到有
Subscribe
注解的Method,将其加入到subscriberMethods列表中返回。

private void findUsingReflectionInSingleClass(FindState findState) {
Method[] methods;
try {
// This is faster than getMethods, especially when subscribers are fat classes like Activities
methods = findState.clazz.getDeclaredMethods();
} catch (Throwable th) {
// Workaround for java.lang.NoClassDefFoundError, see https://github.com/greenrobot/EventBus/issues/149 methods = findState.clazz.getMethods();
findState.skipSuperClasses = true;
}
for (Method method : methods) {
int modifiers = method.getModifiers();
if ((modifiers & Modifier.PUBLIC) != 0 && (modifiers & MODIFIERS_IGNORE) == 0) {
Class<?>[] parameterTypes = method.getParameterTypes();
if (parameterTypes.length == 1) {
Subscribe subscribeAnnotation = method.getAnnotation(Subscribe.class);
if (subscribeAnnotation != null) {
Class<?> eventType = parameterTypes[0];
if (findState.checkAdd(method, eventType)) {
ThreadMode threadMode = subscribeAnnotation.threadMode();
findState.subscriberMethods.add(new SubscriberMethod(method, eventType, threadMode,
subscribeAnnotation.priority(), subscribeAnnotation.sticky()));
}
}
} else if (strictMethodVerification && method.isAnnotationPresent(Subscribe.class)) {
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)) {
String methodName = method.getDeclaringClass().getName() + "." + method.getName();
throw new EventBusException(methodName +
" is a illegal @Subscribe method: must be public, non-static, and non-abstract");
}
}
}


获得这个类(及其父类)符合的方法后,会将其放到缓存列表METHOD_CACHE中。

接着,回到
register
方法,获取subscriberMethods列表后,会遍历这个列表,并调用subscribe()方法

for (SubscriberMethod subscriberMethod : subscriberMethods) {
subscribe(subscriber, subscriberMethod);
}


在subscribe()方法中,最终完成订阅

// Must be called in synchronized block
private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) {
Class<?> eventType = subscriberMethod.eventType;
//创建被观察者对象
Subscription newSubscription = new Subscription(subscriber, subscriberMethod);
//根据类名获取相应的Subscription列表
CopyOnWriteArrayList<Subscription> subscriptions = subscriptionsByEventType.get(eventType);
if (subscriptions == null) {
//subscriptions列表不存在,则创建并添加到subscriptionsByEventType
subscriptions = new CopyOnWriteArrayList<>();
subscriptionsByEventType.put(eventType, subscriptions);
} else {
if (subscriptions.contains(newSubscription)) {
//如果列表中已包含该Subscription,则抛出异常
throw new EventBusException("Subscriber " + subscriber.getClass() + " already registered to event "
+ eventType);
}
}

int size = subscriptions.size();
//根据priority(优先级)添加Subscription到相应的位置
for (int i = 0; i <= size; i++) {
if (i == size || subscriberMethod.priority > subscriptions.get(i).subscriberMethod.priority) {
subscriptions.add(i, newSubscription);
break;
}
}
//将eventType存储到subscriber的typesBySubscriber列表中
List<Class<?>> subscribedEvents = typesBySubscriber.get(subscriber);
if (subscribedEvents == null) {
subscribedEvents = new ArrayList<>();
typesBySubscriber.put(subscriber, subscribedEvents);
}
subscribedEvents.add(eventType);

//如果是sticky (粘性事件)
if (subscriberMethod.sticky) {
//是否考虑所有子类,为true,子类也将能接收到
//从EventBusBuilder可知,eventInheritance默认为true.
if (eventInheritance) {
// Existing sticky events of all subclasses of eventType have to be considered.
// Note: Iterating over all events may be inefficient with lots of sticky events,
// thus data structure should be changed to allow a more efficient lookup
// (e.g. an additional map storing sub classes of super classes: Class -> List<Class>).
Set<Map.Entry<Class<?>, Object>> entries = stickyEvents.entrySet();
for (Map.Entry<Class<?>, Object> entry : entries) {
Class<?> candidateEventType = entry.getKey();
if (eventType.isAssignableFrom(candidateEventType)) { //判断类型是否相同和是其子类或接口
Object stickyEvent = entry.getValue();
//分发事件
checkPostStickyEventToSubscription(newSubscription, stickyEvent);
}
}
} else {
Object stickyEvent = stickyEvents.get(eventType);
//分发事件
checkPostStickyEventToSubscription(newSubscription, stickyEvent);
}
}
}

private void checkPostStickyEventToSubscription(Subscription newSubscription, Object stickyEvent) {
if (stickyEvent != null) {
// If the subscriber is trying to abort the event, it will fail (event is not tracked in posting state)
// --> Strange corner case, which we don't take care of here.
postToSubscription(newSubscription, stickyEvent, Looper.getMainLooper() == Looper.myLooper());
}
}


总结

EventBus的订阅过程主要就是通过Index或者反射遍历
@Subscribe
注解,找到该类(及其父类,这个默认为true,可配置)所有的订阅方法,然后逐个进行subscribe(),添加到相应的集合中,供后续使用。

如果是sticky事件,则从sticky的Set集合中取出相应的事件,如果事件符合当前这个订阅方法,则立即执行。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息