当前位置: 首页 > news >正文

凡科做的网站怎么改壁纸学做快餐在哪个网站

凡科做的网站怎么改壁纸,学做快餐在哪个网站,推几个学习网站,公共空间设计网站源码细节阅读 上一节根据EventBus的使用流程把实现源码大体梳理了一遍#xff0c;因为精力有限#xff0c;所以看源码都是根据实现过程把基本流程看下#xff0c;中间实现细节先忽略#xff0c;否则越看越深不容易把握大体思路#xff0c;这节把一些细节的部分再看看。 …源码细节阅读 上一节根据EventBus的使用流程把实现源码大体梳理了一遍因为精力有限所以看源码都是根据实现过程把基本流程看下中间实现细节先忽略否则越看越深不容易把握大体思路这节把一些细节的部分再看看。 注解函数查找源码逻辑 #EventBus public void register(Object subscriber) {Class? subscriberClass subscriber.getClass();ListSubscriberMethod subscriberMethods subscriberMethodFinder.findSubscriberMethods(subscriberClass);synchronized (this) {for (SubscriberMethod subscriberMethod : subscriberMethods) {subscribe(subscriber, subscriberMethod);}}}在进行注册的时候我们使用subscriberMethodFinder对象的findSubscriberMethods方法来查找到所有该类中以Subscribe注解的函数以下简称为注解函数。让我们继续看下查找部分的逻辑。 ListSubscriberMethod findSubscriberMethods(Class? subscriberClass) {ListSubscriberMethod 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;}}METHOD_CACHE是一个ConcurrentHashMap类型的常量用来保存subscriberClass和对应SubscriberMethod的集合以提高注册效率防止重复查找。 如果METHOD_CACHE缓存中不存在判断变量ignoreGeneratedIndex的值该值是在EventBusBuilder中初始化的表示是否忽略注解生成器默认是false。然后会进入到findUsingInfo函数中进行查找下面再看最后将找到的subscriberMethods添加到METHOD_CACHE中。 private ListSubscriberMethod findUsingInfo(Class? subscriberClass) {FindState findState prepareFindState();findState.initForSubscriber(subscriberClass);return getMethodsAndRelease(findState);}先看findUsingInfo前两行出现一个FindState类它是SubscriberMethodFinder的内部类用来辅助查找订阅事件的方法。 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();}static class FindState {void initForSubscriber(Class? subscriberClass) {this.subscriberClass clazz subscriberClass;skipSuperClasses false;subscriberInfo null;}}prepareFindState()方法主要是返回一个FindState对象先从FIND_STATE_POOL这个缓存池中获取一个现成的如果没有就新建一个对象。获取对象后调用初始化方法将subscriberClass赋值给clazz变量subscriberInfo对象赋值为null。 private ListSubscriberMethod findUsingInfo(Class? subscriberClass) {FindState findState prepareFindState();findState.initForSubscriber(subscriberClass);while (findState.clazz ! null) {findState.subscriberInfo getSubscriberInfo(findState);if (findState.subscriberInfo ! null) {} else {findUsingReflectionInSingleClass(findState);}findState.moveToSuperclass();}return getMethodsAndRelease(findState);}再回到findUsingInfo因为findState.clazz刚赋值过所以不为空。再来看下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;}前面执行initForSubscriber的时候subscriberInfo赋值为null因此第一个if不成立。第二个判断是对象subscriberInfoIndexes该变量也是在EventBusBuilder中初始化的默认是null因此该方法返回值null。 private ListSubscriberMethod findUsingInfo(Class? subscriberClass) {FindState findState prepareFindState();findState.initForSubscriber(subscriberClass);while (findState.clazz ! null) {findState.subscriberInfo getSubscriberInfo(findState);if (findState.subscriberInfo ! null) {} else {findUsingReflectionInSingleClass(findState);}findState.moveToSuperclass();}return getMethodsAndRelease(findState);}再回到findUsingInfo由于getSubscriberInfo返回为null逻辑会走到findUsingReflectionInSingleClass方法中使用反射来获取所有方法下面再看。 获取当前类所有的注解方法后findState.moveToSuperclass()表示修改findState.clazz为subscriberClass的父类Class继续遍历父类中的注解方法。 private static final int MODIFIERS_IGNORE Modifier.ABSTRACT | Modifier.STATIC | BRIDGE | SYNTHETIC;private void findUsingReflectionInSingleClass(FindState findState) {Method[] methods;try {// This is faster than getMethods, especially when subscribers are fat classes like Activitiesmethods findState.clazz.getDeclaredMethods();} catch (Throwable th) {// Workaround for java.lang.NoClassDefFoundError, see https://github.com/greenrobot/EventBus/issues/149}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);}}}上面代码流程如下 通过方法getDeclaredMethods()获取该类中所有声明的方法列表遍历方法列表获取方法的修饰符如果修饰符是public并且不是abstract、static等进入下一步MODIFIERS_IGNORE定义如第一行代码获取方法的参数列表如果参数的个数是1并且使用了Subscribe注解获取唯一的入参进行下一步然后checkAdd()方法用来判断FindState的anyMethodByEventType map是否已经添加过以当前eventType为key的键值对没添加过则返回true就是看看当前类中有没有多个事件相同的注解函数通过注解对象subscribeAnnotation获取threadMode然后新建SubscriberMethod添加到findState.subscriberMethods集合中。 分析完findUsingReflectionInSingleClass这个方法后我们回到findUsingInfo。 private ListSubscriberMethod findUsingInfo(Class? subscriberClass) {FindState findState prepareFindState();findState.initForSubscriber(subscriberClass);while (findState.clazz ! null) {findState.subscriberInfo getSubscriberInfo(findState);if (findState.subscriberInfo ! null) {} else {findUsingReflectionInSingleClass(findState);}findState.moveToSuperclass();}return getMethodsAndRelease(findState);}遍历当前类及其父类通过findUsingReflectionInSingleClass方法找到所有注解方法后通过getMethodsAndRelease返回所有相关方法。 private ListSubscriberMethod getMethodsAndRelease(FindState findState) {ListSubscriberMethod 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;}通过上面的解析知道所有的SubscriberMethod都添加到findState.subscriberMethods集合中这个方法就是把findState.subscriberMethods集合中的内容复制出来然后释放findState中的资源并把findState放到FIND_STATE_POOL缓存中POOL_SIZE常量是4这样下次查找的时候可以重复利用无需每次都新建对象。 以上为注解方法查找的过程。在上面分析的过程中出现了两个变量subscriberInfoIndexes和ignoreGeneratedIndex看样子都是关于索引的分析的时候都是使用的EventBusBuilder中的默认值。看下subscriberInfoIndexes赋值的地方看注释意思是将EventBus注解处理器生成索引添加添加进来。所以注解处理器需要再了解下。 /** Adds an index generated by EventBus annotation preprocessor. */public EventBusBuilder addIndex(SubscriberInfoIndex index) {if (subscriberInfoIndexes null) {subscriberInfoIndexes new ArrayList();}subscriberInfoIndexes.add(index);return this;}Subscriber Index注解处理器 通过上面分析可知EventBus注册事件时主要是在项目运行时通过反射来查找注解方法信息如果项目中有大量的注解方法必然会对项目运行时的性能产生影响。 除了在项目运行时通过反射查找注解方法信息EventBus 还提供了在项目编译时通过注解处理器查找注解方法信息的方式生成一个辅助的索引类来保存这些信息这个索引类就是Subscriber Index。 1、Subscriber Index使用方式 首先要在 app 的build.gradle中加入如下配置 android {defaultConfig {javaCompileOptions {annotationProcessorOptions {// 指定辅助索引类的名称和包名注意这个类时自动生成的不需要我们写arguments [ eventBusIndex : com.jane.demo.MyEventBusIndex ]}}} } dependencies {compile org.greenrobot:eventbus:3.3.1// 引入注解处理器annotationProcessor org.greenrobot:eventbus-annotation-processor:3.3.1 }在项目的Application中添加如下配置以生成一个默认的 EventBus 单例 EventBus.builder().addIndex(new MyEventBusIndex()).installDefaultEventBus();此时重新编译下项目会生成一个MyEventBusIndex类不同的gradle版本生成的位置可能不一样。 生成的MyEventBusIndex代码如下 public class MyEventBusIndex implements SubscriberInfoIndex {private static final MapClass?, SubscriberInfo SUBSCRIBER_INDEX;static {SUBSCRIBER_INDEX new HashMapClass?, SubscriberInfo();putIndex(new SimpleSubscriberInfo(EventBusService.class, true, new SubscriberMethodInfo[] {new SubscriberMethodInfo(onMsgEventReceived, String.class),new SubscriberMethodInfo(onMsgEventReceived, MsgEvent.class),new SubscriberMethodInfo(onMsgEventReceived, org.greenrobot.eventbus.NoSubscriberEvent.class),}));putIndex(new SimpleSubscriberInfo(EventBusActivity.class, true, new SubscriberMethodInfo[] {new SubscriberMethodInfo(onMsgEventReceived, Event.class),}));}private static void putIndex(SubscriberInfo info) {SUBSCRIBER_INDEX.put(info.getSubscriberClass(), info);}Overridepublic SubscriberInfo getSubscriberInfo(Class? subscriberClass) {SubscriberInfo info SUBSCRIBER_INDEX.get(subscriberClass);if (info ! null) {return info;} else {return null;}} }代码中SUBSCRIBER_INDEX是一个HashMap保存了当前注册类的Class类型和其中注解方法的信息。 2、Subscriber Index源码 EventBus.builder().addIndex(new MyEventBusIndex()).installDefaultEventBus();使用的时候获取EventBusBuilder对象然后调用addIndex方法把生成的MyEventBusIndex加入进去。 /** Adds an index generated by EventBus annotation preprocessor. */public EventBusBuilder addIndex(SubscriberInfoIndex index) {if (subscriberInfoIndexes null) {subscriberInfoIndexes new ArrayList();}subscriberInfoIndexes.add(index);return this;}上面的方法是不是比较眼熟就是上面代码分析的时候出现的变量subscriberInfoIndexes赋值函数。这样运行的时候就把之前编译好的索引类的实例保存在subscriberInfoIndexes集合中。然后调用installDefaultEventBus方法创建EventBus实例。 /*** Installs the default EventBus returned by {link EventBus#getDefault()} using this builders values. Must be* done only once before the first usage of the default EventBus.** throws EventBusException if theres already a default EventBus instance in place*/public EventBus installDefaultEventBus() {synchronized (EventBus.class) {if (EventBus.defaultInstance ! null) {throw new EventBusException(Default instance already exists. It may be only set once before its used the first time to ensure consistent behavior.);}EventBus.defaultInstance build();return EventBus.defaultInstance;}}/** Builds an EventBus based on the current configuration. */public EventBus build() {return new EventBus(this);}上面通过build方法以当前EventBusBuilder对象作为参数生成EventBus单例对象并赋值给defaultInstance这样就把subscriberInfoIndexes信息传递给了EventBus。以后调用EventBus 的getDefault()返回的就是这里生成的单例对象里面包含了subscriberInfoIndexes信息。 而且在Application中生成了 EventBus 的默认单例这样就保证了在项目其它地方执行EventBus.getDefault()就能得到就是上面包含subscriberInfoIndexes信息的单例。 在上面分析查找注解函数的时候分析过一个函数 private ListSubscriberMethod findUsingInfo(Class? subscriberClass) {FindState findState prepareFindState();findState.initForSubscriber(subscriberClass);while (findState.clazz ! null) {findState.subscriberInfo getSubscriberInfo(findState);if (findState.subscriberInfo ! null) {····} else {findUsingReflectionInSingleClass(findState);}findState.moveToSuperclass();}return getMethodsAndRelease(findState);}如果没有使用注解处理器的话getSubscriberInfo这个方法返回值是null因此会走到findUsingReflectionInSingleClass通过反射区获取注解方法。现在使用使用注解处理器的话在重新看下这个函数。 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;}Overridepublic SubscriberInfo getSubscriberInfo(Class? subscriberClass) {SubscriberInfo info SUBSCRIBER_INDEX.get(subscriberClass);if (info ! null) {return info;} else {return null;}}如果使用了注解处理器因为subscriberInfoIndexes这个集合不为空遍历获取当前类对应的注解方法列表 index.getSubscriberInfo这个方法实际调用的就是系统生成的MyEventBusIndex中的getSubscriberInfo方法这样就获取到了之前编译生成的注解方法。 private ListSubscriberMethod 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);}通过getSubscriberInfo返回当前类所有注解方法后遍历所有订阅了事件的方法然后加入到subscriberMethods列表中其它的和之前的注册流程一样。 参考文章 EventBus 原理解析
http://www.dnsts.com.cn/news/196516.html

相关文章:

  • 用asp做宠物网站页面在线设计网站大全
  • 南宁武鸣区建设局网站注册公司费用深圳
  • php做网站速成国外seo
  • 餐饮加盟手机网站建设做网站黑网站赚钱么么
  • 如何编辑网站wordpress首页提示
  • 制定企业网站营销推广战略济南精品建站外包公司价格
  • 我做的网站服务器别人没法左键点击下载呢静态网站开发课程网
  • 上海网站制作费用建筑设计经典案例分析
  • 建设跨境电商网站编程培训心得体会
  • 中国建设银行官网首页 网站岳池住房和城乡建设厅网站
  • 公司网站如何宣传推广深圳最好的营销网站建设公司排名
  • 自建网站和租用空间网站旅行社网站模版
  • 免费的舆情网站下载nofollow外链对于网站有提升吗
  • 只买域名不建网站泰安集团网站建设方案
  • 外贸网站怎么做比较好软件外包收费标准
  • 网站建站价格重庆荣昌网站建设
  • 企业网站不备案会怎么样淄博网站建设推广
  • 更换网站空间软件工程师工资高吗
  • 徐汇苏州网站建设网站如何做关健词收录
  • 网站 app 哪个先做互联网app推广工作怎么样
  • 有限公司网站建设 互成网络地址 四川建设企业银行客户号在哪里看
  • 好口碑自适应网站建设做个企业网站需要多少钱
  • 让别人做网站怎样才安全请人建设网站需要注意什么
  • 做网站卖游戏装备百度关键词搜索量
  • 哪个网站是tv域名网页设计素材制作
  • 网站维护是怎么回事四川省黄页企业电话
  • 网站页面构成要素如何建单位内部购物网站
  • 厦门建设工程招标中心的网站太平洋建设21局网站
  • 网站建设人员岗位职责wordpress 3.9.2 下载
  • 电商网站管理四川建设公共查询平台