安卓市场网站源码分享 安卓系统源码在线

大家好,今天给各位分享安卓市场网站源码分享的一些知识,其中也会对安卓系统源码在线进行解释,文章篇幅可能偏长,如果能碰巧解决你现在面临的问题,别忘了关注本站,现在就马上开始吧!

写在前面:如果你看到这篇文章,希望你能够自己对照着源码走一遍,直接反射或者使用索引都会详细分析使用的!

EventBus优点和特性

也许你有个疑问:市面上有很多事件传递框架为何选择EventBus,而不是Otto,Rxbus等,相比较他们都可以满足日常开发需求,只是后两者更新基本停滞,而EventBus还在正常更新维护,选择接入人数也是最多的,同时功能也是最全的,如果你选择了使用该框架,自然了解源码的运行对于调试绝对是有帮助的!我们学知识不能简简单单只是会用而已,要知其然而知其所以然才能进步,提升自己~

优点

简化组件间的通信,解耦事件发送和接受者很好的应用于Activity,Fragment之间,后台线程之间的通信,避免使用多个Intent传递,handler通信等避免复杂的,易于出错的依赖和生命周期问题,比如多个Activity跳转后的回调问题速度响应快,尤其是3.0以后再编译器增加索引轻量大概50K左右的jar包被大量的app所使用,在实际中被验证有很多的高级功能,如线程切换模式,订阅的优先级等

特性

简单易用的注解API:简单的@Subscribe注解放到订阅方法上即可通过编译期的订阅者索引,app就可以不用在运行期通过注解反射拿到订阅了支持事件投递到UI线程,不管事件是从哪个线程发送过来的支持事件和订阅者的继承关系:如事件A是事件B的父类,则发送B类型的事件,该事件也会发送给对于事件A感兴趣的订阅者,对于订阅者也存在相似的继承关系,可以通过eventInheritance(false)关闭该功能,只在本类中调用,父类接口不在回调的即可零设定EventBus直接工作,也可以通过构建者模式调整EventBus的行为,满足你的需求EventBusBuilder.builder()

//通过EventBusBuilder.builder()的方法构建EventBusBuilder对象配置里面的信息以后调用build()方法创建\npublicEventBusbuild(){//创建一个EventBus对象\nreturnnewEventBus(this);\n}\n复制代码\n

注意:通过此方法可以创建多个EventBus对象,且每个配置信息不同,但是每个EventBus的实例都是独立的,也就是说每个EventBuspost事件,只要使用该EventBus注册的订阅者才能接收到,其他EventBus注册的是无法接收的即在EventBus.getEventBus(type).regirst(this)的Activity或者Fragment中的方法都注册到了该type返回的EventBus中啦!

EventBus的构建

首先分析该类的各个属性含义

privatefinalstaticExecutorServiceDEFAULT_EXECUTOR_SERVICE=Executors.newCachedThreadPool();\nExecutorServiceexecutorService=DEFAULT_EXECUTOR_SERVICE;\n//默认线程池,是一个核心0,最大Max,无缓存队列SynchronousQueue;如果大量事件一起发送可能导致OOM,一般需要更改一下线程池配置\n//通过build的方法executorService(executorService)传递进来,主要用于异步和后台事件传递\n\n////在订阅方法中抛出异常时,是否打印日志,在类中注解重写onSubscriberExceptionEvent可以监听到\nbooleanlogSubscriberExceptions=true;\n//没有找到订阅方法,是否打印日志\nbooleanlogNoSubscriberMessages=true;\n//在非订阅SubscriberExceptionEvent事件方法中抛出异常时,是否发送SubscriberExceptionEvent事件\nbooleansendSubscriberExceptionEvent=true;\n//没找到事件订阅方法,是否发送NoSubscriberEvent事件\nbooleansendNoSubscriberEvent=true;\n//在非订阅SubscriberExceptionEvent事件方法中抛出异常时,是否抛出EventBusException异常,默认为false\nbooleanthrowSubscriberException;\nbooleaneventInheritance=true;//发送子事件,是否发送父事件,默认为true,最好改成false,避免不必要的麻烦\n\n//三个参数用于参照订阅方法\nbooleanignoreGeneratedIndex;//是否直接用反射查找订阅方法(就是运行期查找,速度慢耗时,3.0以后优化使用索引的),默认是false\nbooleanstrictMethodVerification;//非注解生成索引时,严格方法验证:当方法不符合格式(public,非abstract,非static,非桥接方法,只有一个参数)时,是否抛出EventBusException异常,默认false\nList<SubscriberInfoIndex>subscriberInfoIndexes;//注解生成的索引,在编译器生成,需要通过android-apt三方插件或annotationProcessor生成\nList<Class<?>>skipMethodVerificationForClasses;//检查以onEvent开头的方法,基本不用啦,都是使用注解自定义方法了\n复制代码\n

注意:对EventBus增加索引,必须在第一个EventBus.regirst之前,因此一般操作都是在Application的oncreate方法中添加//提高性能:第一点是关闭父类以及接口查找分发事件(只有本类调取,父类接口不在回调);//第二点添加索引,索引添加的原理就是提前在编译的时候加载好注册类的相关信息。EventBus.builder().addIndex(newMyEventBusIndex()).eventInheritance(false).installDefaultEventBus();//EventBus.getDefault()获得的即为当前installDefaultEventBus方法生成的,不会在重新创建了,但是如果通过builder.build()重新构建的EventBus就无效了!复制代码这里我们主要通过Event3.0的源码,毕竟用新不用旧嘛

注解Subscribe

通过注解标记订阅方法:同时可以指定threadMode,代表该订阅方法运行的线程,指定sticky,代表是否是粘性事件,指定priority代表优先级(由高到底依次接收,可以更改设置)

@Documented\n@Retention(RetentionPolicy.RUNTIME)\n@Target({ElementType.METHOD})\npublic@interfaceSubscribe{\nThreadModethreadMode()defaultThreadMode.POSTING;\nbooleansticky()defaultfalse;\nintpriority()default0;\n}\n复制代码\n

threadMode:订阅方法运行的线程ThreadMode.POSTING——POST线程,订阅方法运行在发布者所在的线程(默认)ThreadMode.MAIN——UI主线程,订阅方法运行在主线程,发送如果是UI线程直接运行,如果不是通过Handler回调到UI线程运行ThreadMode.BACKGROUND——后台线程,发布者是主线程,订阅方法运行在新开子线程;发布者是子线程,订阅方法运行在发布者所在的线程;(通过线程池创建子线程)ThreadMode.ASYNC——异步线程,订阅方法运行在新开子线程,无论发布者是在哪个线程(同上共用一个线程池)sticky:与Android广播中的sticky概念一致,表示如果当前还未注册,则通过postSticky发送的广播将会保存在内存中,当有注册时就会法将该粘性事件传递给订阅者,即先发送后订阅是可以接收到的!priority:订阅优先级,事件发送以后根据优先级传递,相同优先级根据订阅顺序传递(添加由大->小,调取方法直接轮询由0->size从而达到事件传递性,且事件对象不可变但属性值可变从而可以更改值的传递)

注册register

EventBus通过register注册到Activity或Fragment中

publicvoidregister(Objectsubscriber){//subscriber表示this\nClass<?>subscriberClass=subscriber.getClass();//获取this代表的类\nList<SubscriberMethod>subscriberMethods=subscriberMethodFinder.findSubscriberMethods(subscriberClass);//查找订阅者类中的所有订阅方法\nsynchronized(this){\nfor(SubscriberMethodsubscriberMethod:subscriberMethods){\nsubscribe(subscriber,subscriberMethod);\n}\n}\n}\n\n//SubscriberMethod类的属性\npublicclassSubscriberMethod{\nfinalMethodmethod;//订阅方法\nfinalThreadModethreadMode;//订阅方法在哪个线程执行\nfinalClass<?>eventType;//事件类\nfinalintpriority;//优先级\nfinalbooleansticky;//是否是粘性\n/**Usedforefficientcomparison*/\nStringmethodString;\n复制代码\n

看一下subscriberMethodFinder.findSubscriberMethods如何查找订阅方法

//首先肯定是subscriberMethodFinder的创建:在EventBus的构造函数\nsubscriberMethodFinder=newSubscriberMethodFinder(builder.subscriberInfoIndexes,\nbuilder.strictMethodVerification,builder.ignoreGeneratedIndex);//注意里面传递的参数:索引,方法验证是否符合,是否使用反射调用\n\n//引入EventBus的第一个缓存map集合:键表示当前注册类activity或者Fragment,值表示当前类中的订阅方法的集合\nprivatestaticfinalMap<Class<?>,List<SubscriberMethod>>METHOD_CACHE=newConcurrentHashMap<>();\n\nList<SubscriberMethod>findSubscriberMethods(Class<?>subscriberClass){\nList<SubscriberMethod>subscriberMethods=METHOD_CACHE.get(subscriberClass);\nif(subscriberMethods!=null){//如果注册类已经缓存过了,直接返回\nreturnsubscriberMethods;\n}\n//ignoreGeneratedIndex表示使用反射也就是忽略注解器编译器生成的MyEventBusIndex类,默认是false\nif(ignoreGeneratedIndex){\nsubscriberMethods=findUsingReflection(subscriberClass);//通过反射调用,在运行期\n}else{//我们都会添加编译器生成的代码逻辑\nsubscriberMethods=findUsingInfo(subscriberClass);////从注解器生成的MyEventBusIndex类中获得订阅类的订阅方法信息\n}\nif(subscriberMethods.isEmpty()){\nthrownewEventBusException(&34;+subscriberClass\n+&34;);\n}else{\nMETHOD_CACHE.put(subscriberClass,subscriberMethods);//调用完成以后添加到缓存中\nreturnsubscriberMethods;\n}\n}\n复制代码\n

首先我们先看通过反射来获取订阅类中的订阅方法信息findUsingReflection,通过索引获取的稍后解释

privateList<SubscriberMethod>findUsingReflection(Class<?>subscriberClass){\nFindStatefindState=prepareFindState();\nfindState.initForSubscriber(subscriberClass);//从数组长度为4中取值并初始化Findstate\nwhile(findState.clazz!=null){\nfindUsingReflectionInSingleClass(findState);//找到类中的所有事件响应方法\nfindState.moveToSuperclass();//继续寻找当前类父类中注册的事件响应方法\n}\nreturngetMethodsAndRelease(findState);\n}\n复制代码\n

查找类中的所有事件响应方法

privatevoidfindUsingReflectionInSingleClass(FindStatefindState){\nMethod[]methods;\ntry{\n//获取类中的所有方法,包括私有方法\nmethods=findState.clazz.getDeclaredMethods();\n}catch(Throwableth){\n//Workaroundforjava.lang.NoClassDefFoundError,seehttps://github.com/greenrobot/EventBus/issues/149\nmethods=findState.clazz.getMethods();\nfindState.skipSuperClasses=true;\n}\nfor(Methodmethod:methods){\nintmodifiers=method.getModifiers();//获取方法的属性,private,static等\nif((modifiers&Modifier.PUBLIC)!=0&&(modifiers&MODIFIERS_IGNORE)==0){//如果方法时public,且不是abstract,static,bridge,synthetic编译器生成的\nClass<?>[]parameterTypes=method.getParameterTypes();//获取方法参数,且参数只有1个\nif(parameterTypes.length==1){\nSubscribesubscribeAnnotation=method.getAnnotation(Subscribe.class);//获取以Subscribe注解的方法\nif(subscribeAnnotation!=null){\nClass<?>eventType=parameterTypes[0];//获取事件类\nif(findState.checkAdd(method,eventType)){\nThreadModethreadMode=subscribeAnnotation.threadMode();\nfindState.subscriberMethods.add(newSubscriberMethod(method,eventType,threadMode,\nsubscribeAnnotation.priority(),subscribeAnnotation.sticky()));//将一个类中的所有订阅方法都加入到findstate的集合中\n}\n}\n}elseif(strictMethodVerification&&method.isAnnotationPresent(Subscribe.class)){\nStringmethodName=method.getDeclaringClass().getName()+&34;+method.getName();\nthrownewEventBusException(&34;+methodName+\n&34;+parameterTypes.length);\n}\n}elseif(strictMethodVerification&&method.isAnnotationPresent(Subscribe.class)){\nStringmethodName=method.getDeclaringClass().getName()+&34;+method.getName();\nthrownewEventBusException(methodName+\n&34;);\n}\n}\n}\n\n复制代码\n

我们看一下FindState类的属性

//FindState是SubscriberMethodFinder的静态内部类,类不长,我们都拿过来吧\nstaticclassFindState{\nfinalList<SubscriberMethod>subscriberMethods=newArrayList<>();//订阅方法信息列表\nfinalMap<Class,Object>anyMethodByEventType=newHashMap<>();//以事件类型为key,方法信息为value的集合\nfinalMap<String,Class>subscriberClassByMethodKey=newHashMap<>();//以methodkey为key,订阅者类为value集合(下方的methodkey:method方法所在的类)\nfinalStringBuildermethodKeyBuilder=newStringBuilder(128);//生成methodkey\n//methodkey是由method名字,事件类名称组成\nClass<?>subscriberClass;//订阅者类\nClass<?>clazz;\nbooleanskipSuperClasses;//是否跳过父类\nSubscriberInfosubscriberInfo;\n\nvoidinitForSubscriber(Class<?>subscriberClass){//初始化\nthis.subscriberClass=clazz=subscriberClass;\nskipSuperClasses=false;\nsubscriberInfo=null;\n}\n\nvoidrecycle(){\nsubscriberMethods.clear();\nanyMethodByEventType.clear();\nsubscriberClassByMethodKey.clear();\nmethodKeyBuilder.setLength(0);\nsubscriberClass=null;\nclazz=null;\nskipSuperClasses=false;\nsubscriberInfo=null;\n}\n\n//检查订阅者中注册的事件响应是否可以合法的加入到订阅方法信息中,分为两层检查\nbooleancheckAdd(Methodmethod,Class<?>eventType){//method是订阅方法,eventType是事件类\n//2levelcheck:1stlevelwitheventtypeonly(fast),2ndlevelwithcompletesignaturewhenrequired.\n//Usuallyasubscriberdoesn&34;consume&39;>&34;java.&34;javax.&34;android.&34;Subscriber&34;alreadyregisteredtoevent&unregister(Object)}iscalled,whichischeckedbyqueuedeventdelivery\n*{@linkEventBus34;Subscribertounregisterwasnotregisteredbefore:&34;unchecked&34;Internalerror.Abortstatewasnotreset&34;Nosubscribersregisteredforevent&34;Unknownthreadmode:&34;Unexpectedexception&34;Couldnotsendhandlermessage&34;Couldnotsendhandlermessage&34;Event&34;wasinterruppted&34;Nopendingpostavailable&39;com.neenbedankt.gradle.plugins:android-apt:1.8&39;com.neenbedankt.android-apt&39;org.greenrobot:eventbus:3.0.0&39;org.greenrobot:eventbus-annotation-processor:3.0.1&34;com.monster.android.wild.MyEventBusIndex&39;com.monster.android.wild.MyEventBusIndex&39;org.greenrobot:eventbus:3.0.0&39;org.greenrobot:eventbus-annotation-processor:3.0.1&34;onEvent”,\ncom.monster.android.wild.myeventbusdemo.MainActivity.EventBusEvent.class,ThreadMode.MAIN),\n}));\n\n}\n\nprivatestaticvoidputIndex(SubscriberInfoinfo){\nSUBSCRIBER_INDEX.put(info.getSubscriberClass(),info);\n}\n\n//将会在EventBus在注册过程中使用,等会大家会看到\n@Override\npublicSubscriberInfogetSubscriberInfo(Class<?>subscriberClass){\nSubscriberInfoinfo=SUBSCRIBER_INDEX.get(subscriberClass);\nif(info!=null){\nreturninfo;\n}else{\nreturnnull;\n}\n}\n}\n复制代码\n

上面register中有两个分支,通过ignoreGeneratedIndex是否直接使用反射调用区分,我们当时走的是第一个findUsingReflection,下面看添加索引后的第二个方法findUsingInfo

privateList<SubscriberMethod>findUsingInfo(Class<?>subscriberClass){\nFindStatefindState=prepareFindState();\nfindState.initForSubscriber(subscriberClass);//findstate数组中准备并初始化FindState对象\nwhile(findState.clazz!=null){\n//重点,重点,重点:通过索引获取编译器生成的订阅者信息\nfindState.subscriberInfo=getSubscriberInfo(findState);\nif(findState.subscriberInfo!=null){//注意这里的subscriberInfo实际上是系统自动生成的类SimpleSubscriberInfo对象//如果找到了就遍历订阅类中的订阅方法数组加入进去\nSubscriberMethod[]array=findState.subscriberInfo.getSubscriberMethods();//调用SimpleSubscriberInfo.getSubscriberMethods方法获取订阅方法集合封装成SubscriberMethod[]\nfor(SubscriberMethodsubscriberMethod:array){//轮询,下面就跟反射是一致的操作了\nif(findState.checkAdd(subscriberMethod.method,subscriberMethod.eventType)){\nfindState.subscriberMethods.add(subscriberMethod);\n}\n}\n}else{//否则还是老实的回到反射注册上面去吧\nfindUsingReflectionInSingleClass(findState);\n}\nfindState.moveToSuperclass();\n}\nreturngetMethodsAndRelease(findState);//回收findState对象,以便下次使用\n}\n\n//getSubscriberInfo\nprivateSubscriberInfogetSubscriberInfo(FindStatefindState){\nif(findState.subscriberInfo!=null&&findState.subscriberInfo.getSuperSubscriberInfo()!=null){//新建的findState为null\nSubscriberInfosuperclassInfo=findState.subscriberInfo.getSuperSubscriberInfo();\nif(findState.clazz==superclassInfo.getSubscriberClass()){\nreturnsuperclassInfo;\n}\n}\n//subscriberInfoIndexes是在合适创建的\nif(subscriberInfoIndexes!=null){//subscriberInfoIndexes可能添加多个文件信息,这里我们只是一个\nfor(SubscriberInfoIndexindex:subscriberInfoIndexes){\n//拿到唯一的一个index类即index为:MyEventBusIndex类对象\nSubscriberInfoinfo=index.getSubscriberInfo(findState.clazz);//调用它的getSubscriberInfo(订阅类)即可获得已经put进缓存SUBSCRIBER_INDEX中的方法封装类SimpleSubscriberInfo\nif(info!=null){\nreturninfo;\n}\n}\n}\nreturnnull;\n}\n\n//通过EventBus构造函数中创建通过build传递进来的,如果我们使用索引并且重写build方法传递进来数据了\nsubscriberMethodFinder=newSubscriberMethodFinder(builder.subscriberInfoIndexes,\nbuilder.strictMethodVerification,builder.ignoreGeneratedIndex);\n//将索引值穿进去\nEventBuseventBus=EventBus.builder().addIndex(newMyEventBusIndex()).build();\n复制代码\n

至此:无论是直接反射注册还是通过添加索引在编译器生成文件运行期直接读取注册都分析完成了,不知道你明白了没有呢?最后的话也整理了一份《Android相关源码精编解析》,方便大家笔记学习,有需要的朋友可以点赞+评论支持下,然后评论留言或私信我获取!

关于安卓市场网站源码分享,安卓系统源码在线的介绍到此结束,希望对大家有所帮助。

Published by

风君子

独自遨游何稽首 揭天掀地慰生平