Migracja konfiguracji kompilacji z Groovy do Kotlin

Wtyczka Androida do obsługi Gradle w wersji 4.0 dodała obsługę języka Kotlin w konfiguracji kompilacji Gradle jako zamiennika języka Groovy, języka programowania tradycyjnie używanego w plikach konfiguracyjnych Gradle.

Kotlin jest preferowany zamiast Groovy do pisania skryptów Gradle, ponieważ jest bardziej czytelny i oferuje lepsze sprawdzanie w czasie kompilacji oraz obsługę IDE.

Chociaż Kotlin obecnie oferuje lepszą integrację z edytorem kodu w Android Studio w porównaniu z Groovy, kompilacje z użyciem Kotlina są zwykle wolniejsze niż kompilacje z użyciem Groovy, dlatego przy podejmowaniu decyzji o migracji należy wziąć pod uwagę wydajność kompilacji.

Ta strona zawiera podstawowe informacje o konwertowaniu plików kompilacji Gradle aplikacji na Androida z Groovy na Kotlin. Bardziej szczegółowy przewodnik po migracji znajdziesz w oficjalnej dokumentacji Gradle .

Oś czasu

Od wersji Android Studio Giraffe nowe projekty domyślnie używają Kotlin DSL (build.gradle.kts) do konfiguracji kompilacji. Zapewnia to lepsze możliwości edycji niż Groovy DSL (build.gradle) dzięki podświetlaniu składni, uzupełnianiu kodu i nawigacji do deklaracji. Więcej informacji znajdziesz w artykule zobacz Gradle Kotlin DSL Primer.

Często spotykane terminy

Kotlin DSL: odnosi się głównie do Kotlin DSL wtyczki Androida do obsługi Gradle lub, sporadycznie, do bazowego Kotlin DSL Gradle.

W tym przewodniku po migracji terminy „Kotlin” i „Kotlin DSL” są używane zamiennie. Podobnie terminy „Groovy” i „Groovy DSL” są używane zamiennie.

Nazewnictwo plików skryptów

Nazwy rozszerzeń plików skryptów są oparte na języku, w którym napisany jest plik kompilacji:

  • Pliki kompilacji Gradle napisane w Groovy używają rozszerzenia .gradle.
  • Pliki kompilacji Gradle napisane w Kotlinie używają rozszerzenia .gradle.kts.

Konwertowanie składni

Między Groovy a Kotlinem występują pewne ogólne różnice w składni, dlatego musisz wprowadzić te zmiany w skryptach kompilacji.

Dodawanie nawiasów do wywołań metod

Groovy umożliwia pomijanie nawiasów w wywołaniach metod, natomiast Kotlin ich wymaga. Aby przeprowadzić migrację konfiguracji, dodaj nawiasy do tego typu wywołań metod. Ten kod pokazuje, jak skonfigurować ustawienie w Groovy:

compileSdkVersion 30

To ten sam kod napisany w Kotlinie:

compileSdkVersion(30)

Dodawanie znaku = do wywołań przypisań

Groovy DSL umożliwia pomijanie operatora przypisania = podczas przypisywania właściwości, natomiast Kotlin go wymaga. Ten kod pokazuje, jak przypisywać właściwości w Groovy:

java {
    sourceCompatibility JavaVersion.VERSION_17
    targetCompatibility JavaVersion.VERSION_17
}

Ten kod pokazuje, jak przypisywać właściwości w Kotlinie:

java {
    sourceCompatibility = JavaVersion.VERSION_17
    targetCompatibility = JavaVersion.VERSION_17
}

Konwertowanie ciągów

Oto różnice między ciągami w Groovy a Kotlinie:

  • Cudzysłowy podwójne w przypadku ciągów: Groovy umożliwia definiowanie ciągów za pomocą cudzysłowów pojedynczych, natomiast Kotlin wymaga cudzysłowów podwójnych.
  • Interpolacja ciągów w wyrażeniach z kropkami: w Groovy do interpolacji ciągów w wyrażeniach z kropkami można używać tylko prefiksu $ dla interpolacji ciągów w wyrażeniach z kropkami, ale Kotlin wymaga, aby wyrażenia z kropkami były ujęte w nawiasy klamrowe. Na przykład w Groovy możesz użyć $project.rootDir jak pokazano w tym fragmencie kodu:

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

    W Kotlinie jednak powyższy kod wywołuje toString() w project, a nie w project.rootDir. Aby uzyskać wartość katalogu głównego, ujmij wyrażenie ${project.rootDir} w nawiasy klamrowe:

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

    Więcej informacji znajdziesz w artykule String templates w dokumentacji Kotlina.

Zmienianie rozszerzeń plików

Podczas migracji zawartości do każdego pliku kompilacji dodaj rozszerzenie .kts. Na przykład wybierz plik kompilacji, taki jak settings.gradle. Zmień nazwę pliku na settings.gradle.kts i przekonwertuj jego zawartość na Kotlin. Upewnij się, że po migracji każdego pliku kompilacji projekt nadal się kompiluje.

Najpierw przeprowadź migrację najmniejszych plików, zdobądź doświadczenie, a potem przejdź dalej. W projekcie możesz mieć pliki kompilacji w Kotlinie i Groovy, więc nie spiesz się i dokładnie wykonaj migrację.

Zastępowanie def przez val lub var

Zastąp def przez val lub var, czyli sposób definiowania zmiennych w Kotlinie. Oto deklaracja zmiennej w Groovy:

def building64Bit = false

To ten sam kod napisany w Kotlinie:

val building64Bit = false

Dodawanie prefiksu is do właściwości logicznych

Groovy używa logiki wnioskowania właściwości na podstawie ich nazw. W przypadku właściwości logicznej foo jej wnioskowane metody mogą to być getFoo, setFoo lub isFoo. Dlatego po przekonwertowaniu na Kotlin musisz zmienić nazwy właściwości na wnioskowane metody, które nie są obsługiwane przez Kotlin. Na przykład w przypadku elementów logicznych buildTypes DSL musisz dodać do nich prefiks is. Ten kod pokazuje, jak ustawiać właściwości logiczne w Groovy:

android {
    buildTypes {
        release {
            minifyEnabled true
            shrinkResources true
            ...
        }
        debug {
            debuggable true
            ...
        }
    ...

Poniżej znajduje się ten sam kod w Kotlinie. Zwróć uwagę, że właściwości mają prefiks is.

android {
    buildTypes {
        getByName("release") {
            isMinifyEnabled = true
            isShrinkResources = true
            ...
        }
        getByName("debug") {
            isDebuggable = true
            ...
        }
    ...

Konwertowanie list i map

Listy i mapy w Groovy i Kotlinie są definiowane za pomocą innej składni. Groovy używa [], natomiast Kotlin jawnie wywołuje metody tworzenia kolekcji za pomocą listOf lub mapOf. Podczas migracji pamiętaj, aby zastąpić [] przez listOf lub mapOf.

Oto jak zdefiniować listę w Groovy i Kotlinie:

jvmOptions += ["-Xms4000m", "-Xmx4000m", "-XX:+HeapDumpOnOutOfMemoryError</code>"]

To ten sam kod napisany w Kotlinie:

jvmOptions += listOf("-Xms4000m", "-Xmx4000m", "-XX:+HeapDumpOnOutOfMemoryError")

Oto jak zdefiniować mapę w Groovy i Kotlinie:

def myMap = [key1: 'value1', key2: 'value2']

To ten sam kod napisany w Kotlinie:

val myMap = mapOf("key1" to "value1", "key2" to "value2")

Konfigurowanie typów kompilacji

W Kotlin DSL tylko typy kompilacji debug i kompilacja do publikacji są dostępne niejawnie. Wszystkie inne niestandardowe typy kompilacji należy utworzyć ręcznie.

W Groovy możesz używać typów kompilacji debug, release i niektórych innych bez ich wcześniejszego tworzenia. Ten fragment kodu pokazuje konfigurację z debug, release, i benchmark typami kompilacji w Groovy.

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

Aby utworzyć równoważną konfigurację w Kotlinie, musisz jawnie utworzyć rodzaj kompilacji benchmark.

buildTypes {
 debug {
   ...
 }

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

Migracja z bloku buildscript do bloku plugins

Jeśli kompilacja używa bloku buildscript {} do dodawania wtyczek do projektu, musisz przeprowadzić refaktoryzację, aby zamiast tego używać bloku plugins {}. Blok plugins {} ułatwia stosowanie wtyczek i dobrze współpracuje z katalogami wersji.

Ponadto, gdy używasz bloku plugins {} w plikach kompilacji, Android Studio zna kontekst nawet wtedy, gdy kompilacja się nie powiedzie. Ten kontekst pomaga w naprawianiu plików Kotlin DSL, ponieważ umożliwia IDE Studio uzupełnianie kodu i wyświetlanie innych przydatnych sugestii.

Znajdowanie identyfikatorów wtyczek

Blok buildscript {} dodaje wtyczki do ścieżki klasy kompilacji za pomocą współrzędnychMaven wtyczki, np. com.android.tools.build:gradle:7.4.0, natomiast blok plugins {} używa identyfikatorów wtyczek.

W przypadku większości wtyczek identyfikator wtyczki to ciąg używany podczas stosowania wtyczek za pomocą apply plugin. Na przykład te identyfikatory wtyczek są częścią wtyczki Androida do obsługi Gradle:

  • com.android.application
  • com.android.library
  • com.android.lint
  • com.android.test

Pełną listę wtyczek znajdziesz w repozytorium Maven Google.

Do wtyczek Kotlin można się odwoływać za pomocą wielu identyfikatorów wtyczek. Zalecamy używanie identyfikatora wtyczki z przestrzenią nazw i refaktoryzację z identyfikatora wtyczki w skrócie do identyfikatora wtyczki z przestrzenią nazw zgodnie z tą tabelą:

Identyfikatory wtyczek w skrócie Identyfikatory wtyczek z przestrzenią nazw
kotlin org.jetbrains.kotlin.jvm
kotlin-android org.jetbrains.kotlin.android
kotlin-kapt org.jetbrains.kotlin.kapt
kotlin-parcelize org.jetbrains.kotlin.plugin.parcelize

Możesz też wyszukiwać wtyczki w portalu wtyczek Gradle, centralnym repozytorium Maven i w repozytorium Google Maven. Więcej informacji o tym, jak działają identyfikatory wtyczek, znajdziesz w artykule Developing Custom Gradle Plugins.

Przeprowadzanie refaktoryzacji

Gdy znasz identyfikatory używanych wtyczek, wykonaj te czynności:

  1. Jeśli nadal masz repozytoria wtyczek zadeklarowane w buildscript {} bloku, przenieś je do settings.gradle pliku.

  2. Dodaj wtyczki do bloku plugins {} w pliku build.gradle najwyższego poziomu. Musisz tu określić identyfikator i wersję wtyczki. Jeśli wtyczka nie musi być stosowana do projektu głównego, użyj apply false.

  3. Usuń wpisy classpath z pliku build.gradle.kts najwyższego poziomu.

  4. Zastosuj wtyczki, dodając je do bloku plugins {} w pliku build.gradle na poziomie modułu. Musisz tu określić tylko identyfikator wtyczki, ponieważ wersja jest dziedziczona z projektu głównego.

  5. Usuń wywołanie apply plugin wtyczki z pliku build.gradle na poziomie modułu.

Na przykład ta konfiguracja używa bloku 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")

To równoważna konfiguracja z użyciem bloku 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()
    }
}

Konwertowanie bloku plugins

Stosowanie wtyczek z bloku plugins {} jest podobne w Groovy i Kotlinie. Ten kod pokazuje, jak stosować wtyczki w Groovy, gdy używasz katalogów wersji:

// Top-level build.gradle file
plugins {
   alias libs.plugins.android.application apply false
   ...
}

// Module-level build.gradle file
plugins {
   alias libs.plugins.android.application
   ...
}

Ten kod pokazuje, jak zrobić to samo w Kotlinie:

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

Ten kod pokazuje, jak stosować wtyczki w Groovy, gdy nie używasz katalogów wersji:

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

Ten kod pokazuje, jak zrobić to samo w Kotlinie:

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

Więcej informacji o bloku plugins {} znajdziesz w artykule Applying plugins w dokumentacji Gradle.

Pozostałe postanowienia

Przykłady kodu Kotlin dla innych funkcji znajdziesz na tych stronach dokumentacji:

Znane problemy

Obecnie znanym problemem jest to, że szybkość kompilacji może być mniejsza w Kotlinie niż w Groovy.

Jak zgłaszać problemy

Instrukcje dotyczące podawania informacji potrzebnych do ustalenia priorytetu problemu znajdziesz w artykule Szczegóły dotyczące błędów w narzędziach do kompilacji i Gradle. Następnie, zgłoś błąd w publicznym narzędziu do rejestrowania błędów Google do zgłaszania problemów.

Więcej zasobów

Działający przykład plików kompilacji Gradle napisanych w Kotlinie znajdziesz w przykładowej aplikacji Now In Android w GitHubie.