前言:并非所有的gradle版本都可以实现ksp,我尝试过最低的gradle版本是6.5.1-bin,插件版本则是对应的4.1.0,可以完美运行。而再低的6.1.1-bin,插件版本是4.0.2则会报错。而在gradle版本上到7之后。编译是没问题的,但是其需要的jdk版本是jdk11。所以使用什么样的gradle请根据实际情况选择
目录
ksp是什么
ksp的用途
配置ksp
使用poet生成文件
总结
1、ksp是什么
ksp全拼是:kotlin Symbols Process,kotlin符号处理。
你可以理解ksp是kotlin原生的类似java的APT(Annotation Processing Tool),但是功能更强的用于元编程的一种技术。
ksp的用途
ksp有什么用呢?
我现在也不知道他能用来干多少事情,但是我可以确定的是,ksp最起码可以充当注解处理器。这可能是他唯一的用处,也可能不是。
那同样是用来处理注解的,为什么我需要用ksp而不用以前的apt甚至kapt呢?
无论是apt还是kapt,都是以java的符号处理为基础而运行的。也就是说,我需要处理kotlin的符号,首先需要转成java,然后再处理,这其中就存在性能问题,也就是编译的时间会变长。于是ksp便应运而生了。
下面就进入本篇的正题——如何配置ksp
配置ksp
对于ksp配置影响较大的部分就是gradle。这里使用的版本是:
gradle version:6.5.1-bin
gradle 插件 version:4.1.0
kotlin version : 1.5.31
1、创建一个modue用于存放注解
2、创建module用于存放符号处理器
2.1、修改build.gradle文件:
plugins {
id 'kotlin'
id 'org.jetbrains.kotlin.jvm' //jvm插件
}
compileKotlin {
kotlinOptions {
jvmTarget = "1.8"
//需要设置,否者可能无法生成文件
freeCompilerArgs += "-Xuse-experimental=com.squareup.kotlinpoet.ksp.KotlinPoetKspPreview"
freeCompilerArgs += "-Xuse-experimental=com.google.devtools.ksp.KspExperimental"
}
}
dependencies {
//ksp依赖
implementation("com.google.devtools.ksp:symbol-processing-api:$ksp_version")//ksp_version = "1.5.31-1.0.0"
//poet依赖,poet用于生成kotlin文件
implementation("com.squareup:kotlinpoet:1.10.2")
implementation("com.squareup:kotlinpoet-ksp:1.10.0")
//注解依赖
implementation project(":anno")
}
2.2、创建符号处理器
class TestSProcessor(private val environment: SymbolProcessorEnvironment) :
SymbolProcessor {
private val logger = environment.logger
override fun process(resolver: Resolver): List<KSAnnotated> {
//logging和info级别的log有可能无法在build中看见,请使用warn或error级别
//logger.logging("test log run")
//logger.info("test info run")
logger.warn("test warn run")
return emptyList()
}
}
2.3、创建符号处理器提供者
class TestSProcessorProvider : SymbolProcessorProvider {
override fun create(environment: SymbolProcessorEnvironment): SymbolProcessor {
//返回值是符号处理器
return TestSProcessor(environment)
}
}
在main下创建resources文件夹,并按第二大点的截图添加文件。在文件中加入
com.erolc.complier.TestSProcessorProvider,是你符号处理器提供者的完整类名。
2.5、在app的build.gradle配置ksp
plugins {
//...
id 'com.google.devtools.ksp' version "$ksp_version" //加入ksp插件
}
dependencies {
ksp project(":complier")//使用符号处理器
implementation project(":anno")//加入注解
}
这样就可以进行调试了。如果在build中看到以下日志证明配置初步完成:
使用poet生成文件
在符号处理器(TestSProcessor)的processs方法中加入以下简单代码用于测试:
override fun process(resolver: Resolver): List<KSAnnotated> {
resolver.getSymbolsWithAnnotation(Test::class.qualifiedName!!)
.filterIsInstance<KSClassDeclaration>()
.toSet().forEach {
FileSpec.builder(
it.packageName.asString(),
"${it.simpleName.asString()}$\$Test"
).addFunction(FunSpec.builder("test")
.addStatement("return 12")
.build())
.build().writeTo(KspContext.environment.codeGenerator, false)
}
}
现在不需要知道这段代码的具体意思,只需要知道这段代码是识别Test注解,并生成一个文件,文件中只有一个test方法即可。
然后我们在app模块中使用一下Test注解
@Test
class DataDemo
调试一下,如果在app模块的相应位置中生成对应文件代表生成文件也没问题了。
生成的文件内部是这样的:
但是这时我们去使用这个test方法会报错
这是因为并代码不知道怎么去找这个方法,所以需要在app模块中配置一下sourceSrc,让代码能找到它
android{
//...
buildTypes{
//...
debug{
sourceSets {
main {
java {
srcDirs += ['build/generated/ksp/debug/kotlin']
}
// gradle.7.0配置
// kotlin{
// srcDirs = ['build/generated/ksp/debug/kotlin']
// }
}
}
}
}
}
注意:如果是通过release的方式build,那么该文件就会出现在release文件夹内而不是debug。而sourceSets也需要设置在buildTypes为release中。
这时我们再看会生成的文件,会是这样的:
证明sourceSets已经起作用了,而我们使用的地方也不报错了:
到这里,ksp的配置就完成了。
总结
ksp可以像apt那样,识别kotlin代码,然后去解析,并通过kotlinpote去生成kotlin文件,是kotlin原生的符号处理技术。完整的源码已经上传到github上,希望对你有帮助。传送门