Android Gradle 插件 4.0 添加了对在 Gradle 构建配置中使用 Kotlin 的支持,以替代 Groovy,Groovy 是传统上在 Gradle 配置文件中使用的编程语言。
与 Groovy 相比,Kotlin 更适合编写 Gradle 脚本,因为 Kotlin 可读性更高,并提供更好的编译时检查和 IDE 支持。
尽管与 Groovy 相比,Kotlin 目前在 Android Studio 的代码编辑器中提供了更好的集成,但使用 Kotlin 的构建往往比使用 Groovy 的构建速度慢,因此在决定是否迁移时要考虑构建性能。
本页提供了有关将 Android 应用程序的 Gradle 构建文件从 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”可互换使用。
脚本文件命名
脚本文件扩展名基于构建文件所用语言
- 用 Groovy 编写的 Gradle 构建文件使用
.gradle
文件扩展名。 - 用 Kotlin 编写的 Gradle 构建文件使用
.gradle.kts
文件扩展名。
转换语法
Groovy 和 Kotlin 在语法上存在一些普遍差异,因此您需要在整个构建脚本中应用这些更改。
在方法调用中添加括号
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
调用toString()
,而不是对project.rootDir
调用。要获取根目录的值,请将${project.rootDir}
表达式用花括号括起来。myRootDirectory = "${project.rootDir}/tools/proguard-rules-debug.pro"
要了解更多信息,请参阅 Kotlin 文档中的 字符串模板。
重命名文件扩展名
在迁移每个构建文件的内容时,将其扩展名追加为 .kts
。例如,选择一个构建文件,例如 settings.gradle
文件。将该文件重命名为 settings.gradle.kts
,并将文件的内容转换为 Kotlin。确保你的项目在迁移每个构建文件后仍然可以编译。
先迁移最小的文件,获得经验,然后继续进行。你的项目中可以同时存在 Kotlin 和 Groovy 构建文件,所以请花时间仔细进行迁移。
将 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")
配置构建类型
在 Kotlin DSL 中,只有调试和发布构建类型是隐式可用的。所有其他自定义构建类型必须手动创建。
在 Groovy 中,你可以使用调试、发布和某些其他构建类型,而无需事先创建它们。以下代码片段展示了在 Groovy 中使用 debug
、release
和 benchmark
构建类型的配置。
buildTypes {
debug {
...
}
release {
...
}
benchmark {
...
}
}
要在 Kotlin 中创建等效配置,你必须显式创建 benchmark
构建类型。
buildTypes {
debug {
...
}
release {
...
}
register("benchmark") {
...
}
}
从 buildscript 块迁移到 plugins 块
如果你的构建使用 buildscript {}
块来向项目添加插件,你应该重构为使用 plugins {}
块。 plugins {}
块使应用插件变得更容易,并且它与 版本目录 很好地配合使用。
此外,当你在构建文件中使用 plugins {}
块时,Android Studio 即使在构建失败的情况下也能意识到上下文。此上下文有助于修复 Kotlin DSL 文件,因为它允许 Studio IDE 执行代码补全并提供其他有用的建议。
查找插件 ID
虽然 buildscript {}
块使用插件的 Maven 坐标 将插件添加到构建类路径,例如 com.android.tools.build:gradle:7.4.0
,但 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 |
---|---|
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 Central 仓库 和 Google Maven 仓库 上搜索插件。阅读 开发自定义 Gradle 插件 以了解有关插件 ID 工作原理的更多信息。
执行重构
一旦你知道了你使用的插件的 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 块
从 plugins {}
块应用插件在 Groovy 和 Kotlin 中类似。以下代码展示了在使用 版本目录 时,如何在 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 {}
块,请参阅 从构建文件中删除签名信息。 - 如果你使用项目范围的属性,请参阅 配置项目范围的属性。
已知问题
目前,一个 已知问题 是,Kotlin 的构建速度可能比 Groovy 慢。
如何报告问题
有关如何提供我们处理你的问题所需信息的说明,请参阅 构建工具和 Gradle 错误的详细信息。然后,使用 Google 的 公共问题跟踪器 提交错误。
更多资源
有关使用 Kotlin 编写的 Gradle 构建文件的实际示例,请参阅 GitHub 上的 Now In Android 示例应用程序。