EventBus源码解析02-订阅者注册
2017-08-25 07:21
381 查看
接着,我们来看EventBus的订阅过程
这里,首先获取订阅者的class,接着,通过
一般通过
在
再来看下
获得这个类(及其父类)符合的方法后,会将其放到缓存列表METHOD_CACHE中。
接着,回到
在subscribe()方法中,最终完成订阅
如果是sticky事件,则从sticky的Set集合中取出相应的事件,如果事件符合当前这个订阅方法,则立即执行。
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集合中取出相应的事件,如果事件符合当前这个订阅方法,则立即执行。
相关文章推荐
- [EventBus源码解析] 订阅者处理消息的四种ThreadMode
- EventBus源码解析(二)——注册
- EventBus源码解析(四)-解除注册
- EventBus源码解析(三)-注册
- EventBus源码解析(五)-普通事件发布
- 注册中心 Eureka 源码解析 —— 项目结构简介
- Android EventBus源码解析 带你深入理解EventBus
- Spring源码学习IOC(4):IoC容器解析Bean定义资源并注册解析后的Bean
- Android EventBus 3.0 使用及源码解析一
- EventBus源码分析(四): 发送Event和响应注册的回调方法
- EventBus 3.0源码解析
- C#软件授权、注册、加密、解密模块源码解析并制作注册机生成license
- 注册中心 Eureka 源码解析 —— Eureka-Server 启动(二)之 EurekaBootStrap
- Android EventBus源码解析 带你深入理解EventBus
- 注册中心 Eureka 源码解析 —— Eureka-Client 初始化(一)之 EurekaInstanceConfig
- Android EventBus源码解析 带你深入理解EventBus
- EventBus源码解析 带你深入理解EventBus
- Spring源码解析之一 ------ 默认标签的解析注册(IOC的第一步)
- EventBus 源码解析
- 注册中心 Eureka 源码解析 —— 项目结构简介