将 build 配置从 Groovy 迁移到 Kotlin

Android Gradle 插件 4.0 添加了对在 Gradle build 中使用 Kotlin 的支持 来替代 Groovy 传统方式用于 Gradle 配置文件。

在编写 Gradle 脚本时,Kotlin 比 Groovy 更优,因为 Kotlin 可读性更高,并提供更好的编译时检查和 IDE 支持。

虽然 Kotlin 目前在 Android Studio 代码中的集成效果更好, 与 Groovy 相比,使用 Kotlin 进行构建往往比使用 Kotlin 使用 Groovy 构建,因此在决定是否使用 Groovy 时,请考虑构建性能。 迁移。

本页提供了有关转换 Android 应用 Gradle build 文件从 Groovy 到 Kotlin。实现更全面的迁移 请参阅 Gradle 的 官方文档

时间轴

从 Android Studio Giraffe 开始,新项目将使用 Kotlin DSL (build.gradle.kts)。这能提供更好的 使用语法与 Groovy DSL (build.gradle) 相比, 突出显示、代码补全和导航到声明。如需了解详情, 请参阅 Gradle Kotlin DSL 入门

常用术语

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 替换为 valvar

def 替换为 valvar,这是在 Kotlin 中定义变量的方式。以下是 Groovy 中的变量声明:

def building64Bit = false

以下是使用 Kotlin 编写的相同代码:

val building64Bit = false

为布尔值属性添加 is 前缀

Groovy 使用属性推断逻辑 指定属性。对于布尔值属性 foo,其推导的方法可以是 getFoosetFooisFoo因此,在转换为 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 使用 listOfmapOf 显式调用集合创建方法。迁移时,请务必将 [] 替换为 listOfmapOf

以下是 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 中具有 debugreleasebenchmark build 类型的配置。

buildTypes {
 debug {
   ...
 }
 release {
   ...
 }
 benchmark {
   ...
 }
}

要在 Kotlin 中创建等效配置,您必须显式创建 benchmark build 类型。

buildTypes {
 debug {
   ...
 }

 release {
   ...
 }
 register("benchmark") {
    ...
 }
}

从 buildscript 迁移到插件块

如果您的构建使用 buildscript {} 块以向项目添加插件,您应该重构为使用 plugins {} 屏蔽。plugins {} 代码块可让您更轻松地应用插件, 适合 版本目录

此外,在 build 文件中使用 plugins {} 代码块时, 即使构建失败,Android Studio 也能感知上下文。背景信息 有助于修复 Kotlin DSL 文件,因为它允许 Studio IDE 执行代码补全并提供其他实用建议。

查找插件 ID

buildscript {} 代码块使用如下代码将插件添加到 build 类路径: 该 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
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 RepositoryGoogle Maven 制品库。 已读 开发自定义 Gradle 插件 详细了解插件 ID 的工作原理。

执行重构

知道所用插件的 ID 后,请执行以下步骤:

  1. 如果您在 buildscript {} 中声明的插件仍然存在 将其移至settings.gradle 文件。

  2. 将插件添加到顶层的 plugins {} 代码块中 build.gradle 文件。您需要指定 ID 和 此处使用的是该插件。如果插件不需要 应用于根项目,请使用 apply false

  3. 从顶级 build.gradle.kts 文件中移除 classpath 条目。

  4. 将插件添加到 plugins {} 代码块中的以下操作以应用插件: 模块级 build.gradle 文件。您只需指定插件的 ID,因为该版本是从根项目继承而来。

  5. 从模块级中移除插件的 apply plugin 调用 build.gradle 文件。

例如,此设置使用 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 {} 代码块应用插件的过程类似。 以下代码展示了如何在您使用 版本目录

// 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)
   ...
}

以下代码展示了如何在不使用时 使用版本目录:

// 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 {} 代码块,请参阅应用 插件

其他

如需了解 Kotlin 实现其他功能的代码示例,请参阅以下文档页面:

已知问题

目前,一个已知问题 使用 Kotlin 的构建速度可能比使用 Groovy 慢。

如何报告问题

如需了解如何提供对问题进行分类所需的信息,请参阅构建工具和 Gradle bug 详细信息。然后,使用 Google 公开问题跟踪器来提交 bug。

更多资源

如需查看使用 Kotlin 编写的 Gradle build 文件的可运行示例,请参阅 Now In Android 示例应用