先把图放上来
这是Android组件化设计 — Gradle的神奇之处中的关于组件化的架构图,其中,组件1 … 组件4之前是不能相互依赖的,那么如果组件1想要调起组件2,只能通过基础层组件的路由能力。
在组件之前没有依赖的情况下,相互调用,那么可以通过类加载的方法,例如app壳想要调起注册模块,那么可以拿到注册模块的RegisterActivity的全类名,通过类加载的方式启动
fun jump(view: View) { //com.study.register.RegisterActivity // val RegisterActivity = Class.forName("com.study.register.RegisterActivity") startActivity(Intent(this,RegisterActivity)) }
或者可以通过注册路由表的方式,将所有的Activity的类信息注册到全局的Map中,如果存在成百的Actiivty,需要每个Activity手动去注册。
那么有没有一种方式,在编译的过程中就能拿到全部的类信息,注册到路由表中,避免手动注册这种方式
组件化路由基础 APT1 定义路由注解2 注解处理器 APT Compiler3 注解处理前的初始化配置踩坑:创建的注解处理器没有工作
APT是注解处理工具,用于编译期在源代码中查找注解,根据注解生成新的类 函数;像Eventus、ButterKnife、ARouter都是编译期生成新的类,像EventBus是采用传统的生成代码方式,直接写字符串生成
传统方式
//1 先写包名 直接write package com.study.modulelization //2 再写类名 class HttpConfig { //3 如果有方法 就再写方法名 companion object{ private const val DEBUG = "http://106.108.2.3//test-baidu.com" private const val RELEASE = "http://106.108.2.3//baidu.com" } }
而像ButterKnife、ARouter采用的是JavaPoet方式,引入了面向对象的思想,跟传统方式相反,不如传统方式的可读性强
1 定义路由注解@Retention(AnnotationRetention.BINARY) @Target(AnnotationTarget.TYPE) annotation class LayRouter( val group:String, val path:String = "" )
Kotlin中的注解,跟Java中的注解类似,在自定义注解时,需要声明元注解;
其中Retention代表注解存在的时期,SOURCE(源码时期)、BINARY(编译期,跟Java区分,Java编译期为Class)、RUNTIME(运行时)
Target为声明作用的对象,TYPE(类、接口等)、FUNCTION(函数,但不包含构造方法)、CONSTRUCTOR(构造方法)、PROPERTY_GETTER / PROPERTY_SETTER(get set方法)、FIELD(属性)
2 注解处理器 APT Compiler在声明注解之后,需要注解处理器来处理注解,在系统编译时,会从全部的代码中查找自定义的注解,生成代码,那么注解处理器相当于一个服务,在后台运行,检测代码,因此需要做一些配置
layout_compiler # build.gradle
dependencies { //背后的服务 annotationProcessor 'com.google.auto.service:auto-service:1.0-rc4' //JavaPoet implementation "com.squareup:javapoet:1.13.0" //要处理的注解 implementation project(path: ':lay_router') }
谷歌的AutoService可以在编译时在后台检测代码,查找自定义的注解
3 注解处理前的初始化配置@AutoService(Processor::class) class AnnotationProcessor : AbstractProcessor() { // *** 作Element的工具类(类、函数、属性等) private var elementTool:Elements? = null //类信息 *** 作类 继承 实现 等实现方式 private var typeTool:Types? = null //日志打印 private var message:Messager? = null //文件输出 private var filer:Filer? = null //支持的注解类型,就是我们自定义的注解 override fun getSupportedAnnotationTypes(): MutableSet{ return mutableSetOf(LayRouter::class.java.canonicalName) } //支持的Java版本 Java 1.8 override fun getSupportedSourceVersion(): SourceVersion { return SourceVersion.RELEASE_8 } //支持的参数选项,就是从app壳传递到注解处理器的参数 override fun getSupportedOptions(): MutableSet { return mutableSetOf("moduleName") } override fun init(processingEnv: ProcessingEnvironment?) { super.init(processingEnv) elementTool = processingEnv!!.elementUtils typeTool = processingEnv.typeUtils message = processingEnv.messager filer = processingEnv.filer message!!.printMessage(Diagnostic.Kind.NOTE,"init 注解处理器初始化") val s = processingEnv.options["moduleName"] message!!.printMessage(Diagnostic.Kind.NOTE,"--------->$s") } //处理注解 override fun process(p0: MutableSet ?, p1: RoundEnvironment?): Boolean { return false } }
AbstractProcessor是注解处理器,后续会有一个专门的章节介绍,配合编译的过程。
当一个类被注解修饰之后,AnnotationProcessor需要拿到这个类的信息以便于生成代码,因此需要创建一些能够获取类信息的工具,ProcessingEnvironment中,存在我们想要的工具
public interface ProcessingEnvironment { MapgetOptions(); //日志打印 Messager getMessager(); //文件生成 Filer getFiler(); //类 接口 属性的 *** 作,都可以看做一个元素 Elements getElementUtils(); //类信息的 *** 作 Types getTypeUtils(); //获取版本信息 SourceVersion getSourceVersion(); Locale getLocale(); }
在app壳工程中,使用注解,那么在注解处理器中(lay_compiler)怎么拿到app壳工程的参数信息呢,那么在app壳中通过Gradle向注解处理器传递参数
现在是Kotlin的工程,在传参的时候通过kapt — arguments — arg传递参数
kapt { arguments{ arg("moduleName","zhijiedamamamfamfafafafa") } }
AnnotationProcessor # init
override fun init(processingEnv: ProcessingEnvironment?) { super.init(processingEnv) elementTool = processingEnv!!.elementUtils typeTool = processingEnv.typeUtils message = processingEnv.messager filer = processingEnv.filer message!!.printMessage(Diagnostic.Kind.NOTE,"init 注解处理器初始化") val s = processingEnv.options["moduleName"] message!!.printMessage(Diagnostic.Kind.NOTE,"--------->$s") }
通过ProcessingEnvironment获取options,通过key来获取value,将参数从message打印出来
这样,注解处理器的初始化 *** 作就完成,如果app壳中想要使用我们自定义的注解处理器,那么就需要依赖
app壳 # build.gradle
dependencies { dependency.each { k, v -> implementation v } if (rootProject.isRelease) { //依赖包 implementation project(path: ':register') implementation project(path: ':lay_router') //kotlin使用kapt依赖 注解处理器, //Java使用 annotationProcessor kapt project(path: ':lay_compiler') } testImplementation 'junit:junit:4.+' androidTestImplementation 'androidx.test.ext:junit:1.1.3' androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' }踩坑:创建的注解处理器没有工作
你以为这样就可以完成了吗,错误❎,这里踩了一个坑,导包依赖之后,无论怎么编译也进不到初始化方法中
当完成注解处理器的初始化 *** 作后,需要在main文件夹下,创建resource — meta-INF — services下,创建javax.annotation.processing.Processor文件,其中需要声明我们创建的注解处理器,就相当于注册了
这里这个坑,真的是踩了一下午…
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)