將建構設定從 Groovy 遷移至 Kotlin

Android Gradle 外掛程式 4.0 已新增在 Gradle 建構設定中使用 Kotlin 的支援功能,以取代 Groovy,Groovy 是 Gradle 設定檔中傳統使用的程式設計語言。

在編寫 Gradle 指令碼時,Kotlin 比 Groovy 更受歡迎,因為 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 入門」。

常見詞彙

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 (而非 project.rootDir) 上的 toString()。如要取得根目錄的值,請用大括號括住 ${project.rootDir} 運算式:

        myRootDirectory = "${project.rootDir}/tools/proguard-rules-debug.pro"
        

    詳情請參閱 Kotlin 說明文件中的「字串範本」一節。

重新命名副檔名

遷移建構檔案時,請將 .kts 附加至每個建構檔案。舉例來說,請選取 settings.gradle 檔案等建構檔案,將檔案重新命名為 settings.gradle.kts,並將檔案內容轉換為 Kotlin。請確保在遷移每個建構檔案後,您的專案仍可編譯。

請先遷移最小的檔案,獲得經驗後再遷移其他檔案。您可以在專案中同時使用 Kotlin 和 Groovy 建構檔案,因此可以審慎地慢慢遷移。

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")

設定建構類型

在 Kotlin DSL 中,只有偵錯和發布建構類型能以默示方式使用。所有其他自訂建構類型都必須手動建立。

在 Groovy 中,您不必預先建立,即可使用偵錯、發布和其他特定建構類型。以下程式碼片段顯示 Groovy 中具有 debugreleasebenchmark 建構類型的設定。

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

如要在 Kotlin 中建立相對應的設定,您必須明確建立 benchmark 建構類型。

buildTypes {
 debug {
   ...
 }

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

從 buildscript 遷移至外掛程式區塊

如果您的版本使用 buildscript {} 區塊在專案中新增外掛程式,則應改用 plugins {} 區塊進行重構。plugins {} 區塊可讓您更輕鬆地套用外掛程式,也適用於版本目錄

此外,在建構檔案中使用 plugins {} 區塊時,即使建構作業失敗,Android Studio 也會知道結構定義。這個結構定義可讓 Studio IDE 執行程式碼完成作業,並提供其他實用建議,因此有助於修正 Kotlin DSL 檔案。

找出外掛程式 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 中央存放區Google Maven 存放區中搜尋外掛程式。請參閱「開發自訂 Gradle 外掛程式」,進一步瞭解外掛程式 ID 的運作方式。

執行重構

知道所用外掛程式的 ID 後,請按照下列步驟操作:

  1. 如果您仍在 buildscript {} 區塊中宣告外掛程式存放區,請改為將其移至 settings.gradle 檔案。

  2. 將外掛程式新增至頂層 build.gradle 檔案的 plugins {} 區塊。您必須在此指定外掛程式的 ID 和版本。如果不需要將外掛程式套用至根專案,請使用 apply false

  3. 從頂層 build.gradle.kts 檔案移除 classpath 項目。

  4. 如要套用外掛程式,請將外掛程式新增至模組層級 build.gradle 檔案的 plugins {} 區塊。由於版本會從根專案繼承,因此您只需要在此處指定外掛程式的 ID。

  5. 從模組層級 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()
    }
}

轉換外掛程式區塊

在 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 程式碼範例,請參閱下列說明文件頁面:

已知問題

目前的已知問題是使用 Kotlin 的建構速度可能比 Groovy 慢。

如何回報問題

如要瞭解如何提供問題分類所需的資訊,請參閱「建構工具和 Gradle 錯誤的詳細資料」。接著,請使用 Google 的公開 Issue Tracker 回報錯誤。

其他資源

如需使用 Kotlin 編寫的 Gradle 建構檔案實例,請參閱 GitHub 上的 Now In Android 範例應用程式