Android Gradle 插件 4.0 支持在 Gradle build 配置中使用 Kotlin,用于替代 Groovy(过去在 Gradle 配置文件中使用的编程语言)。
Kotlin 比 Groovy 更适合用于编写 Gradle 脚本,因为采用 Kotlin 编写的代码可读性更高,并且 Kotlin 提供了更好的编译时检查和 IDE 支持。
虽然与 Groovy 相比,Kotlin 当前能更好地在 Android Studio 的代码编辑器中集成,但采用 Kotlin 的构建速度往往比采用 Groovy 慢,因此在决定是否迁移时应考虑构建性能。
本页介绍了有关将 Android 应用的 Gradle build 文件从 Groovy 转换为 Kotlin 的基本信息。如需查看更全面的迁移指南,请参阅 Gradle 的官方文档。
时间轴
从 Android Studio Giraffe 开始,新项目默认使用 Kotlin DSL (build.gradle.kts
) 进行构建配置。与 Groovy DSL (build.gradle
) 相比,这提供了更好的编辑体验,包括语法突出显示、代码补全和导航到声明。如需了解详情,请参阅 Gradle Kotlin DSL Primer。
常用术语
Kotlin DSL:主要是指 Android Gradle 插件 Kotlin DSL,有时也指底层 Gradle Kotlin DSL。
在本迁移指南中,“Kotlin”和“Kotlin DSL”可互换使用。同样,“Groovy”和“Groovy DSL”可以互换使用。
脚本文件命名
脚本文件扩展名取决于编写 build 文件所用的语言:
- 用 Groovy 编写的 Gradle build 文件使用
.gradle
文件扩展名。 - 用 Kotlin 编写的 Gradle build 文件使用
.gradle.kts
文件扩展名。
转换语法
Groovy 和 Kotlin 的语法之间存在一些普遍差异,因此您需要在 build 脚本中应用以下更改。
为方法调用添加圆括号
Groovy 允许您在方法调用中省略圆括号,而 Kotlin 则要求使用圆括号。如需迁移配置,请为这些类型的方法调用添加圆括号。以下代码展示了如何在 Groovy 中配置设置:
compileSdkVersion 30
以下是使用 Kotlin 编写的相同代码:
compileSdkVersion(30)
为分配调用添加 =
Groovy DSL 允许您在分配属性时省略赋值运算符“=
”,而 Kotlin 则要求使用它。以下代码展示了如何在 Groovy 中分配属性:
java {
sourceCompatibility JavaVersion.VERSION_17
targetCompatibility JavaVersion.VERSION_17
}
以下代码展示了如何在 Kotlin 中分配属性:
java {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
转换字符串
以下是 Groovy 和 Kotlin 在字符串方面的差异:
- 用于定义字符串的双引号:虽然 Groovy 允许使用单引号来定义字符串,但 Kotlin 要求使用双引号。
-
基于句点表达式的字符串插值:在 Groovy 中,对于句点表达式的字符串插值,您可以仅使用“
$
”前缀,但 Kotlin 要求您用大括号将句点表达式括起来。例如,在 Groovy 中,您可以使用如以下代码段所示的$project.rootDir
:myRootDirectory = "$project.rootDir/tools/proguard-rules-debug.pro"
不过,在 Kotlin 中,上述代码会针对
project
(而非project.rootDir
)调用toString()
。如需获取根目录的值,请使用大括号括住${project.rootDir}
表达式:myRootDirectory = "${project.rootDir}/tools/proguard-rules-debug.pro"
如需了解详情,请参阅 Kotlin 文档中的字符串模板。
重命名文件扩展名
请在迁移每个 build 文件的内容时将 .kts
添加到其文件扩展名后。例如,选择一个 build 文件(如 settings.gradle
文件)。将该文件重命名为 settings.gradle.kts
,然后将其内容转换为 Kotlin。请确保您的项目在迁移每个 build 文件之后仍然可以编译。
请先迁移最小的文件以便积累经验,然后再继续。项目中可以混合使用 Kotlin 和 Groovy build 文件,因此您无需着急,可以小心细致地进行迁移。
将 def
替换为 val
或 var
将 def
替换为 val
或 var
,这是在 Kotlin 中定义变量的方式。以下是 Groovy 中的变量声明:
def building64Bit = false
以下是使用 Kotlin 编写的相同代码:
val building64Bit = false
为布尔值属性添加 is
前缀
Groovy 会根据属性名称使用属性推导逻辑。对于布尔值属性 foo
,其推导的方法可以是 getFoo
、setFoo
或 isFoo
。因此,在转换为 Kotlin 后,您需要为 Kotlin 不支持的推导方法更改属性名称。例如,对于 buildTypes
DSL 布尔值元素,您需要为它们添加 is
前缀。以下代码展示了如何在 Groovy 中设置布尔值属性:
android {
buildTypes {
release {
minifyEnabled true
shrinkResources true
...
}
debug {
debuggable true
...
}
...
以下是 Kotlin 中的相同代码:请注意,这些属性带有 is
前缀。
android {
buildTypes {
getByName("release") {
isMinifyEnabled = true
isShrinkResources = true
...
}
getByName("debug") {
isDebuggable = true
...
}
...
转换列表和映射
Groovy 和 Kotlin 中的列表和映射使用不同的语法进行定义。Groovy 使用 []
,而 Kotlin 使用 listOf
或 mapOf
显式调用集合创建方法。迁移时,请务必将 []
替换为 listOf
或 mapOf
。
以下是 Groovy(相对于 Kotlin)定义列表的方法:
jvmOptions += ["-Xms4000m", "-Xmx4000m", "-XX:+HeapDumpOnOutOfMemoryError</code>"]
以下是使用 Kotlin 编写的相同代码:
jvmOptions += listOf("-Xms4000m", "-Xmx4000m", "-XX:+HeapDumpOnOutOfMemoryError")
以下是 Groovy(相对于 Kotlin)定义映射的方法:
def myMap = [key1: 'value1', key2: 'value2']
以下是使用 Kotlin 编写的相同代码:
val myMap = mapOf("key1" to "value1", "key2" to "value2")
配置 build 类型
在 Kotlin DSL 中,只有调试和发布 build 类型是隐式提供的。所有其他自定义 build 类型都必须手动创建。
在 Groovy 中,您无需先创建就可以使用调试、发布和某些其他 build 类型。以下代码段展示了 Groovy 中具有 debug
、release
和 benchmark
build 类型的配置。
buildTypes {
debug {
...
}
release {
...
}
benchmark {
...
}
}
如需在 Kotlin 中创建等效配置,您必须显式创建 benchmark
build 类型。
buildTypes {
debug {
...
}
release {
...
}
register("benchmark") {
...
}
}
从 buildscript 迁移到 plugins 块
如果您的 build 使用 buildscript {}
块向项目添加插件,您应进行重构,改用 plugins {}
块。plugins {}
块可让您更轻松地应用插件,并且与版本目录搭配使用效果出色。
此外,如果您在 build 文件中使用 plugins {}
块,Android Studio 将能够获知相关上下文信息,即使在构建失败时也是如此。此上下文有助于修复 Kotlin DSL 文件,因为它让 Studio IDE 能够执行代码补全并提供其他有用的建议。
查找插件 ID
虽然 buildscript {}
块使用插件的 Maven 坐标(例如 com.android.tools.build:gradle:7.4.0
)将插件添加到 build 类路径,但 plugins {}
块改为使用插件 ID。
对于大多数插件,插件 ID 是您使用 apply plugin
应用插件时使用的字符串。例如,以下插件 ID 属于 Android Gradle 插件:
com.android.application
com.android.library
com.android.lint
com.android.test
您可以在 Google Maven 制品库中找到完整的插件列表。
多个插件 ID 可以引用 Kotlin 插件。我们建议您使用命名空间型插件 ID,并根据下表从缩写形式重构为命名空间型插件 ID:
简写插件 ID | 命名空间型插件 ID |
---|---|
kotlin |
org.jetbrains.kotlin.jvm |
kotlin-android |
org.jetbrains.kotlin.android |
kotlin-kapt |
org.jetbrains.kotlin.kapt |
kotlin-parcelize |
org.jetbrains.kotlin.plugin.parcelize |
您还可以在 Gradle 插件门户、Maven 中央存储库和 Google Maven 制品库中搜索插件。如需详细了解插件 ID 的运作方式,请参阅开发自定义 Gradle 插件。
执行重构
知道您使用的插件的 ID 后,请执行以下步骤:
如果您仍在
buildscript {}
块中声明了插件代码库,请改为将其移至settings.gradle
文件。将插件添加到顶级
build.gradle
文件中的plugins {}
代码块。您需要在此处指定插件的 ID 和版本。如果插件不需要应用于根项目,请使用apply false
。从顶级
build.gradle.kts
文件中移除classpath
条目。将插件添加到模块级
build.gradle
文件中的plugins {}
代码块中,以应用这些插件。您只需在此处指定插件 ID,因为版本会从根项目继承。从模块级
build.gradle
文件中移除插件的apply plugin
调用。
例如,以下设置使用了 buildscript {}
块:
// Top-level build.gradle file
buildscript {
repositories {
google()
mavenCentral()
gradlePluginPortal()
}
dependencies {
classpath("com.android.tools.build:gradle:7.4.0")
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.8.0")
...
}
}
// Module-level build.gradle file
apply(plugin: "com.android.application")
apply(plugin: "kotlin-android")
以下是使用 plugins {}
块的等效设置:
// Top-level build.gradle file
plugins {
id 'com.android.application' version '7.4.0' apply false
id 'org.jetbrains.kotlin.android' version '1.8.0' apply false
...
}
// Module-level build.gradle file
plugins {
id 'com.android.application'
id 'org.jetbrains.kotlin.android'
...
}
// settings.gradle
pluginManagement {
repositories {
google()
mavenCentral()
gradlePluginPortal()
}
}
转换 plugins 块
在 Groovy 和 Kotlin 中,通过 plugins {}
块应用插件的方式是类似的。以下代码展示了当您使用版本目录时如何在 Groovy 中应用插件:
// Top-level build.gradle file
plugins {
alias libs.plugins.android.application apply false
...
}
// Module-level build.gradle file
plugins {
alias libs.plugins.android.application
...
}
以下代码展示了如何在 Kotlin 中执行相同的操作:
// Top-level build.gradle.kts file
plugins {
alias(libs.plugins.android.application) apply false
...
}
// Module-level build.gradle.kts file
plugins {
alias(libs.plugins.android.application)
...
}
以下代码展示了当您不使用版本目录时如何在 Groovy 中应用插件:
// Top-level build.gradle file
plugins {
id 'com.android.application' version '7.3.0' apply false
...
}
// Module-level build.gradle file
plugins {
id 'com.android.application'
...
}
以下代码展示了如何在 Kotlin 中执行相同的操作:
// Top-level build.gradle.kts file
plugins {
id("com.android.application") version "7.3.0" apply false
...
}
// Module-level build.gradle.kts file
plugins {
id("com.android.application")
...
}
如需详细了解 plugins {}
块,请参阅 Gradle 文档中的应用插件。
其他
如需了解 Kotlin 实现其他功能的代码示例,请参阅以下文档页面:
- 如果您有 ProGuard 配置,请参阅启用缩减、混淆和优化。
- 如果您有
signingConfig {}
块,请参阅从 build 文件中移除签名信息。 - 如果您使用项目全局属性,请参阅配置项目全局属性。
已知问题
目前,一个已知问题是采用 Kotlin 的构建速度往往比采用 Groovy 慢。
如何报告问题
如需了解如何提供对问题进行分类所需的信息,请参阅构建工具和 Gradle bug 详细信息。然后,使用 Google 公开问题跟踪器来提交 bug。
更多资源
如需查看使用 Kotlin 编写的 Gradle build 文件的可运行示例,请参阅 GitHub 上的 Now in Android 示例应用。