简介
Kotlin Symbol Processing (KSP) 是Google提供的基于Kotlin编译器提供的符号处理工具,相比KAPT有更快的速度。
简单使用方法
此处以Jetpack AndroidX Room的KSP为例,在app的build.gradle.kts中添加以下代码
plugins {
// ...
// 导入gradle插件
id("com.google.devtools.ksp") version "<kotlin-version>-<ksp-version>"
// ...
}
// ...
// 设定Room的KSP参数
ksp {
arg("room.schemaLocation", "$projectDir/schemas")
arg("room.incremental", "true")
}
// ...
// 更换kapt为ksp(因为Room的Kapt和KSP是写在一起的,所以直接更换就好了)
dependencies {
// ...
ksp("androidx.room:room-compiler:<room-version>")
// ...
}
使用自定义的KSP
只需要创建一个Kotlin module然后按照KSP文档中说明的方法,继承SymbolProcessor
和SymbolProcessorProvider
并实现方法即可。
具体的实现方法请参阅KSP官方文档。如果对Kapt了解的话,还是很容易上手的。另外,目前使用需要添加编译器参数,KotlinPoet也需要KSP版本。
简略的build.gradle.kts如下所示:
plugins {
kotlin("jvm")
}
tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile>().configureEach {
kotlinOptions {
jvmTarget = ProjectConfig.javaVersion.toString()
freeCompilerArgs = freeCompilerArgs + listOf(
"-opt-in=com.google.devtools.ksp.KspExperimental"
)
}
}
dependencies {
implementation("com.squareup:kotlinpoet-ksp:<kotlinpoet-ksp-version>")
implementation("com.google.devtools.ksp:symbol-processing-api:<ksp-version>")
}
最后别忘了在resources/META-INF/services
文件夹下添加com.google.devtools.ksp.processing.SymbolProcessorProvider
文件。
其中按行书写KSP的调用类即可。
目前存在的问题
- 目前由于Android Gradle Plugin (AGP)没有正确识别1.8.21-1.0.11版本的KSP生成的代码,会出现可以编译但是编辑相关代码时红线error的问题。
- 在使用中也可能会有第一次编译并生成代码成功,修改部分代码后再次编译就无法正确生成代码的问题。
解决方案
- 在app的build.gradle.kts中添加以下代码指定不同variant使用不同的ksp路径
import com.android.build.api.variant.impl.VariantImpl
android {
// ...
androidComponents {
onVariants { it ->
if (it is VariantImpl) {
it.variantData.addJavaSourceFoldersToModel(file("$buildDir/generated/ksp/${it.buildType}/kotlin"))
}
}
}
// ...
}
另一种解决方案:
import com.android.build.gradle.AppExtension
extensions.getByType<AppExtension>().apply {
applicationVariants.all {
addJavaSourceFoldersToModel(file("$buildDir/generated/ksp/$name/kotlin"))
}
}
注:此处使用的Gradle Kotlin DSL编写,若要用groovy请自行修改
- 在gradle.properties中添加
# 停用KSP的增量编译
ksp.incremental=false
原理:目前AS(2022.2.1 patch 2)每次编译会删除所有旧的生成的代码并添加新的,KSP为了减少工作量会使用增量编译的方式只更新有关联更改的文件。Room的KSP会自动重复添加但是自定义的KSP却不会(目前没找到具体原因,如果有思路欢迎评论)。
注:出现代码无法生成的情况应该是和AGP(8.0.2)兼容性存在问题,关闭增量编译可以解决问题但是可能会减慢速度,所以还需要等Google修复。如果不存在问题不建议添加这个属性。
One more thing
只有在项目中所有的kapt都替换为ksp时才会有较好的编译体验。
Made By XFY9326