Współzależności między narzędziami i bibliotekami

Zależności kompilacji to komponenty zewnętrzne wymagane do pomyślnego skompilowania projektu. Kompilacja może zależeć od bibliotek, wtyczek, podprojektów, pakietu Android SDK, narzędzi takich jak kompilatory Kotlin i Java, środowisk programistycznych takich jak Android Studio oraz samego Gradle.

Każda zależność może wymagać innych zależności. Nazywamy je zależnościami przechodnimi. Mogą one szybko zwiększyć ogólną liczbę zależności używanych przez aplikację. Gdy chcesz uaktualnić zależność, niezależnie od tego, czy jest to biblioteka, narzędzie czy pakiet Android SDK, może to spowodować uaktualnienie wielu innych zależności.

Często nie powoduje to żadnych problemów, ponieważ wiele bibliotek stosuje schemat znany jako wersjonowanie semantyczne. Te biblioteki ograniczają typy wprowadzanych zmian, aby zapewnić zgodność z niższymi wersjami.

Semantyczna obsługa wersji ma format major.minor.patch. Na przykład w numerze wersji 4.8.3 cyfra 4 oznacza wersję major, 8 – wersję minor, a 3 – numer patch. Gdy zmienia się część major, biblioteka może zawierać zmiany powodujące niezgodność w interfejsie API lub działaniu. Może to wpłynąć na działanie kompilacji lub aplikacji.

Gdy zmieniają się części minor (nowe funkcje) lub patch (poprawki błędów), deweloperzy biblioteki informują, że biblioteka jest nadal zgodna i nie powinna mieć wpływu na aplikację.

Relacje w kompilacji

Kompilacje Androida zawierają relacje między:

  • Kod źródłowy – kod i zasoby, nad którymi masz kontrolę.
  • Zależności bibliotek – zewnętrzne biblioteki lub moduły, które projekt i projekty podrzędne uwzględniają podczas kompilacji.
  • Narzędzia – kompilatory, wtyczki i pakiety SDK, które przekształcają kod źródłowy w aplikację lub bibliotekę.
Zależności kompilacji i ich relacje
Rysunek 1. Buduj relacje

Kod źródłowy

Kod źródłowy to kod w języku Kotlin lub Java, który piszesz w aplikacji lub bibliotece. (szczegółowe informacje o korzystaniu z C++ znajdziesz w artykule Android NDK).

Kod źródłowy zależy od bibliotek (w tym bibliotek środowiska wykonawczego Kotlin i Java) oraz pakietu Android SDK i wymaga odpowiedniego kompilatora Kotlin lub Java.

Niektóre kody źródłowe zawierają adnotacje, które wymagają dodatkowego przetwarzania. Jeśli na przykład piszesz kod Jetpack Compose, dodajesz adnotacje takie jak @Composable, które muszą zostać przetworzone przez wtyczkę kompilatora Compose Kotlin. Inne adnotacje mogą być przetwarzane przez procesor symboli Kotlin (KSP) lub oddzielne narzędzia do przetwarzania adnotacji.

Zależności bibliotek

Biblioteki zawierają kod bajtowy pobierany w ramach aplikacji. Może to być plik JAR Javy, biblioteka Androida (AAR) lub podprojekt w kompilacji. Wiele bibliotek stosuje wersjonowanie semantyczne, które może pomóc Ci zrozumieć, kiedy po uaktualnieniu zachowują zgodność (lub nie).

Biblioteki często mają zależności przechodnie od innych bibliotek. Dzięki temu nie musisz zarządzać wszystkim bezpośrednio – określasz zależności bezpośrednie, a Gradle pobiera je razem z zależnościami przechodnimi. Uaktualnienie zależności bezpośrednich może też spowodować uaktualnienie ich zależności przejściowych.

Czasami biblioteka może wymagać minimalnych wersji pakietu Android SDK w czasie działania (minSdk) lub w czasie kompilowania (compileSdk). Jest to konieczne, gdy biblioteka używa funkcji zawartych w pakiecie Android SDK lub w udostępnianych przez niego interfejsach API JDK. Efektywna wartość minSdk aplikacji to najwyższa wartość minSdk wymagana przez aplikację i wszystkie jej bezpośrednie i pośrednie zależności od bibliotek.

Korzystanie z niektórych bibliotek może wymagać użycia określonej wtyczki Gradle. Te wtyczki pomocnicze często instalują procesory symboli Kotlin lub inne procesory adnotacji, które generują kod lub modyfikują kompilację źródła, aby umożliwić korzystanie z funkcji biblioteki. Na przykład Jetpack Room zawiera adnotacje i KSP, który przekształca je w wygenerowany kod, aby pobierać i modyfikować dane w bazie danych. Jetpack Compose wymaga wtyczki kompilatora Compose, aby modyfikować funkcje z adnotacjami i zarządzać tym, jak i kiedy są one ponownie uruchamiane.

Narzędzia

Gradle

Gradle to narzędzie do kompilacji, które odczytuje pliki kompilacji i generuje aplikację lub bibliotekę, a także udostępnia interfejs API dla wtyczek, aby rozszerzyć jego możliwości. Gradle uruchamia wiele procesów na co najmniej 1 maszynie wirtualnej Javy, a jego wtyczki Javy wywołują narzędzia Javy w JDK.

Wtyczki Gradle

Wtyczki Gradle rozszerzają Gradle, definiując nowe zadania i konfigurację. Zastosowanie wtyczki do kompilacji umożliwia korzystanie z określonych funkcji kompilacji, które są skonfigurowane jako dane w skryptach kompilacji. W przypadku kompilacji na Androida najważniejszą wtyczką Gradle jest wtyczka Androida do obsługi Gradle (AGP).

Kompilatory

Kompilator Kotlin lub Java przekształca kod źródłowy w wykonywalny kod bajtowy. Kompilator Kotlin udostępnia interfejs API wtyczki, który umożliwia przeprowadzanie analizy zewnętrznej i generowanie kodu bezpośrednio w kompilatorze, z dostępem do przeanalizowanej struktury kodu.

Wtyczki kompilatora

Wtyczki kompilatora przeprowadzają analizę i generują kod wewnątrz kompilatora Kotlin, gdy analizuje on Twój kod. Są instalowane, gdy zastosujesz ich wtyczki Gradle do kompilacji.

Android SDK

Android SDK zawiera platformę Androida i interfejsy API Javy dla konkretnej wersji Androida oraz odpowiednie narzędzia. Te narzędzia pomagają zarządzać pakietem SDK, tworzyć aplikacje oraz komunikować się z urządzeniami z Androidem i je emulować.

Każda wersja pakietu Android SDK udostępnia określone interfejsy API Javy, do których Twój kod źródłowy może mieć dostęp, oraz obsługę odlukrzania, która umożliwia korzystanie z tych interfejsów API we wcześniejszych wersjach Androida.

JDK

Pakiet Java Development Kit, który zawiera biblioteki i pliki wykonywalne Javy do kompilowania kodu źródłowego i uruchamiania aplikacji w Javie. W kompilacji Androida używanych jest kilka pakietów JDK. Więcej informacji znajdziesz w artykule Wersje Javy w kompilacjach Androida.

Zakresy Gradle

Gradle grupuje zależności bibliotek w różne zakresy (nazywane konfiguracjami w interfejsie Gradle API), co pozwala określić różne zestawy zależności bibliotek do użycia w różnych częściach kompilacji. Na przykład prawdopodobnie nie chcesz uwzględniać bibliotek testowych, takich jak JUnit, w opublikowanej aplikacji lub bibliotece, ale potrzebujesz ich podczas tworzenia i wykonywania testów jednostkowych. Zakresów możesz też używać do dodawania procesorów symboli lub adnotacji w celu analizowania kodu.

Na przykład AGP definiuje zakresy implementation i api, czyli sposób określania, czy zależność powinna być widoczna dla użytkowników podprojektu. Opisy tych i innych zakresów używanych w kompilacji na Androida znajdziesz w artykule Konfigurowanie zależności.

Dodaj zależności biblioteki w bloku dependencies plików kompilacji jako ciągi tekstowe group:artifact:version:

Kotlin

// In a module-level build script
// explicit dependency strings ("group:artifact:version")
dependencies {
    implementation("com.example:library1:1.2.3")
    api("com.example:library2:1.1.1")
}

Dynamiczny

// In a module-level build script
// explicit dependency strings ("group:artifact:version")
dependencies {
    implementation 'com.example:library1:1.2.3'
    api 'com.example:library2:1.1.1'
}

lub w katalogu wersji:

# Version catalog - gradle/libs.versions.toml
[versions]
exampleLib = "1.2.3"
examplePlugin = "2.3.4"

[libraries]
example-library = { group = "com.example", name = "library", version.ref = "exampleLib" }

[plugins]
example-plugin = { id = "com.example.plugin", version.ref = "examplePlugin" }

i określ wygenerowane zmienne w plikach kompilacji:

Kotlin

// In a module-level build script
// Using a version catalog
plugins {
    alias(libs.plugins.example.plugin)
}

dependencies {
    implementation(libs.example.library)
}

Dynamiczny

// In a module-level build script
// Using a version catalog
plugins {
    alias(libs.plugins.example.plugin)
}

dependencies {
    implementation libs.example.library
}