Migracja konfiguracji kompilacji z Groovy do Kotlin

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

Kotlin jest preferowany do pisania skryptów Gradle zamiast Groovy, ponieważ jest bardziej czytelny i oferuje lepszą kontrolę czasu kompilacji oraz obsługę IDE.

Chociaż Kotlin oferuje obecnie lepszą integrację w edytorze kodu w Android Studio niż Groovy, kompilacje używające tej usługi są zwykle wolniejsze niż kompilacje z użyciem Groovy, dlatego przy podejmowaniu decyzji o migracji warto rozważyć zwiększenie wydajności.

Na tej stronie znajdziesz podstawowe informacje o konwertowaniu plików kompilacji Gradle w aplikacji na Androida z Groovy na Kotlin. Bardziej kompleksowy przewodnik po migracji znajdziesz w oficjalnej dokumentacji Gradle.

Oś czasu

Od Android Studio Giraffe nowe projekty domyślnie korzystają z konfiguracji DSL Kotlin (build.gradle.kts). Takie rozwiązanie zapewnia wygodniejsze edytowanie niż wersja Groovy DSL (build.gradle) z wyróżnieniem składni, uzupełnianiem kodu i przejściem do deklaracji. Aby dowiedzieć się więcej, przeczytaj film Gradle Kotlin DSL Primer.

Często używane terminy

Kotlin DSL: odnosi się głównie do wtyczki Android Gradle (Kotlin DSL) lub, czasami, podobnej wersji DSL w Gradle Kotlin.

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

Nazwy plików skryptów

Nazwy rozszerzeń plików skryptu zależą od języka, w którym napisany jest plik kompilacji:

  • Pliki kompilacji Gradle napisane w aplikacji Groovy mają rozszerzenie nazwy pliku .gradle.
  • Pliki kompilacji Gradle napisane w Kotlin używają rozszerzenia nazwy pliku .gradle.kts.

Konwertowanie składni

Istnieją pewne ogólne różnice w składni w Groovy i Kotlin, więc musisz zastosować te zmiany w wszystkich skryptach kompilacji.

Dodaj nawiasy do wywołań metody

Element Groovy umożliwia pomijanie nawiasów w wywołaniach metod, a Kotlin ich wymaga. Aby przenieść konfigurację, dodaj nawiasy do takich wywołań metod. Ten kod pokazuje, jak skonfigurować ustawienie w Groovy:

compileSdkVersion 30

Ten sam kod jest zapisany w Kotlin:

compileSdkVersion(30)

Dodaj użytkownika = do przypisanych połączeń

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

java {
    sourceCompatibility JavaVersion.VERSION_17
    targetCompatibility JavaVersion.VERSION_17
}

Ten kod pokazuje, jak przypisać właściwości w Kotlin:

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

Konwertuj ciągi

Oto różnice w ciągach znaków między Groovy a Kotlin:

  • cudzysłowy podwójne w przypadku ciągów znaków: ciągi znaków można definiować za pomocą pojedynczych cudzysłowów, natomiast Kotlin wymaga cudzysłowów podwójnych.
  • Interpolacja ciągów znaków w wyrażeniach kropkowanych: w Groovy możesz używać samego prefiksu $ do interpolacji ciągów znaków w wyrażeniach kropkowanych, a Kotlin wymaga ujęcia przerywanego wyrażenia nawiasami klamrowymi. Na przykład w Groovy możesz użyć $project.rootDir, jak w tym fragmencie:

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

    Natomiast w Kotlin poprzedni kod wywołuje toString() w project, a nie w project.rootDir. Aby uzyskać wartość katalogu głównego, umieść wyrażenie ${project.rootDir} w nawiasach klamrowych:

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

    Więcej informacji znajdziesz w sekcji Szablony ciągów znaków w dokumentacji Kotlin.

Zmienianie nazw rozszerzeń plików

Dołącz .kts do każdego pliku kompilacji podczas migracji jego zawartości. Na przykład wybierz plik kompilacji, taki jak plik settings.gradle. Zmień nazwę pliku na settings.gradle.kts i przekonwertuj jego zawartość na Kotlin. Dopilnuj, aby po migracji każdego pliku kompilacji projekt nadal się kompilował.

Najpierw przenieś najmniejsze pliki, zdobądź doświadczenie, a potem przejdź dalej. Możesz mieć w projekcie mieszankę plików kompilacji Kotlin i Groovy, więc śmiało rób to uważnie.

Zamień def na val lub var

Zastąp def wartością val lub vartak zdefiniujesz zmienne w Kotlin. To jest deklaracja zmiennej w Groovy:

def building64Bit = false

Ten sam kod jest zapisany w Kotlin:

val building64Bit = false

Właściwości wartości logicznej poprzedź prefiksem is

Groovy używa logiki odliczenia właściwości na podstawie nazw właściwości. W przypadku właściwości logicznej foo jej metodami zdeformowanymi mogą być getFoo, setFoo lub isFoo. Po przekonwertowaniu na Kotlin musisz zmienić nazwy właściwości na metody wydedukowane, które nie są obsługiwane przez Kotlin. Na przykład elementy logiczne DSL buildTypes muszą poprzedzić je ciągiem is. Ten kod pokazuje, jak ustawić właściwości wartości logicznych w Groovy:

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

Poniżej znajduje się ten sam kod w aplikacji Kotlin. Pamiętaj, że właściwości są poprzedzone znakiem is.

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

Konwertuj listy i mapy

Listy i mapy w Groovy i Kotlin są definiowane przy użyciu innej składni. Groovy używa metody [], a Kotlin bezpośrednio wywołuje metody zbierania danych za pomocą listOf lub mapOf. Pamiętaj, aby podczas migracji zastąpić [] elementem listOf lub mapOf.

Oto jak zdefiniować listę w stylu Groovy i Kotlin:

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

Ten sam kod jest zapisany w Kotlin:

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

Oto jak zdefiniować mapę w grze Groovy i Kotlin:

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

Ten sam kod jest zapisany w Kotlin:

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

Konfigurowanie typów kompilacji

W DSL Kotlin domyślnie dostępne są tylko typy kompilacji służące do debugowania i publikowania wersji. Pozostałe niestandardowe typy kompilacji należy tworzyć ręcznie.

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

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

Aby utworzyć równoważną konfigurację w Kotlin, musisz bezpośrednio utworzyć typ kompilacji benchmark.

buildTypes {
 debug {
   ...
 }

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

Migracja z kompilacji do bloku wtyczek

Jeśli kompilacja wykorzystuje blok buildscript {} do dodawania wtyczek do projektu, zastosuj refaktoryzację, aby zamiast tego użyć bloku plugins {}. Blok plugins {} ułatwia stosowanie wtyczek i dobrze działa z katalogami wersji.

Dodatkowo gdy używasz bloku plugins {} w plikach kompilacji, Android Studio wie o kontekście nawet wtedy, gdy kompilacja się nie powiedzie. Ten kontekst pomaga wprowadzić poprawki w plikach DSL Kotlin, ponieważ umożliwia IDE Studio wykonywanie kodu uzupełniającego i przedstawianie innych przydatnych sugestii.

Znajdowanie identyfikatorów wtyczek

Blok buildscript {} dodaje wtyczki do ścieżki klasy kompilacji przy użyciu współrzędnych Maven (np. com.android.tools.build:gradle:7.4.0), ale blok plugins {} używa identyfikatorów wtyczki.

W przypadku większości wtyczek identyfikator wtyczki to ciąg znaków używany podczas ich stosowania za pomocą polecenia 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 Google Maven.

Do wtyczek Kotlin może się odwoływać wiele identyfikatorów wtyczek. Zalecamy użycie identyfikatora wtyczki z przestrzenią nazw i refaktoryzację ze skrótu na identyfikator wtyczki z przestrzenią nazw, korzystając z tej tabeli:

Skrócone identyfikatory wtyczek Identyfikatory wtyczek z przestrzeniami 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ż szukać wtyczek w portalu wtyczek Gradle, repozytorium Maven Central i repozytorium Google Maven. Więcej informacji o sposobie działania identyfikatorów wtyczek znajdziesz w artykule o tworzeniu niestandardowych wtyczek do Gradle.

Wykonaj refaktoryzację

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

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

  2. Dodaj wtyczki do bloku plugins {} w pliku build.gradle najwyższego poziomu. Musisz tutaj podać identyfikator i wersję wtyczki. Jeśli wtyczka nie musi być stosowana w projekcie głównym, 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. Wystarczy, że podasz tu 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 w tej konfiguracji używany jest blok 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")

Jest 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 wtyczek

Stosowanie wtyczek z bloku plugins {} wygląda podobnie w Groovy i Kotlin. Ten kod pokazuje, jak stosować wtyczki w Groovy podczas korzystania z 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 w 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)
   ...
}

Poniższy 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 w 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")
   ...
}

Więcej informacji o bloku plugins {} znajdziesz w sekcji o stosowaniu wtyczek w dokumentacji Gradle.

Inne

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

Znane problemy

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

Jak zgłaszać problemy

Instrukcje udostępniania informacji potrzebnych do sklasyfikowania problemu znajdziesz w artykule Szczegóły dotyczące narzędzi do kompilacji i błędów Gradle. Następnie zgłoś błąd za pomocą publicznego narzędzia Google do rejestrowania problemów.

Więcej materiałów

Praktyczny przykład plików kompilacji Gradle napisanych w Kotlin znajdziesz w przykładowej aplikacji Now In na Androida w serwisie GitHub.