Android Gradle 插件 4.0 增加了对在 Gradle build 配置中使用 Kotlin 的支持,以替代 Groovy(Gradle 配置文件中传统使用的编程语言)。
在编写 Gradle 脚本方面,Kotlin 比 Groovy 更高,因为 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 制品库中找到完整的插件列表。
Kotlin 插件可由多个插件 ID 引用。我们建议您使用命名空间型插件 ID,并根据下表将简写形式的插件 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 示例应用。