Pliki kompilacji określają bezpośrednie zależności, ale każda z nich może wymagać innych zależności. Te pośrednie zależności szybko zwiększają ogólny wykres zależności, często o sprzeczne wersje.
Gdy zmienią się części minor
(nowe funkcje) lub patch
(poprawki błędów), biblioteka nadal będzie kompatybilna i nie powinna mieć większego wpływu na Twoją aplikację.
Załóżmy na przykład, że Twoja aplikacja jest zależna od biblioteki A i biblioteki B, które z kolei są zależne od różnych wersji biblioteki C.
W takim przypadku Gradle domyślnie wybiera najnowszą wersję biblioteki C, co może spowodować problemy z kompilacją lub środowiskiem wykonawczym. W tym przykładzie biblioteka C jest rozwiązywana do wersji 2.1.1, ale zwróć uwagę, że biblioteka A poprosiła o bibliotekę C w wersji 1.0.3. Zmieniła się większość numeru wersji, co wskazuje na niezgodne zmiany, takie jak usunięcie funkcji lub typów. Może to spowodować awarię połączeń nawiązywanych z biblioteki A.
Aplikacja może mieć zależności bezpośrednie, które są też zależnościami pośrednimi.
W takim przypadku nowsze zależności pośrednie mogą zastąpić wersję, którą bezpośrednio żądasz w aplikacji.
Gradle sprawdza wszystkie wersje kandydatów dla wszystkich zależności na wykresie, aby określić najnowszą wersję każdej zależności. Aby określić, które wersje każdej zależności zostały rozwiązane przez Gradle, możesz użyć podstawowych zadań Gradle i wtyczek innych firm. Porównanie zmian w tym rozdzieleniu jest kluczowe dla zrozumienia i ograniczenia ryzyka związanego z uaktualnieniem.
Możesz na przykład użyć zadania Gradle dependencies
, uruchamiając ./gradlew
app:dependencies
, aby wyświetlić drzewo wszystkich zależności używanych przez moduł aplikacji. Gdy uruchomimy to w aplikacji, która korzysta z bibliotek widocznych na rysunku 2,
1: releaseRuntimeClasspath - Runtime classpath of /release.
2: +--- org.jetbrains.kotlin:kotlin-stdlib:2.0.0
3: | +--- ... (omitted for brevity) ...
4: +--- com.sample:library.a:1.2.3
5: | +--- com.sample:library.c:2.1.1
6: | | \--- org.jetbrains.kotlin:kotlin-stdlib:2.0.0 (*)
7: | \--- org.jetbrains.kotlin:kotlin-stdlib:2.0.0 (*)
8: +--- com.sample:library.c:1.4.1 -> 2.1.1 (*)
Ten fragment raportu pokazuje niektóre zależności rozwiązane w przypadku konfiguracji releaseRuntimeClasspath
.
Gdy w raporcie zależności widzisz ->
, oznacza to, że żądający (Twoja aplikacja lub inna biblioteka) używa wersji zależności, której nie oczekuje. W wielu przypadkach nie powoduje to żadnych problemów, ponieważ większość bibliotek jest napisana z myślą o wstecznej zgodności. Niektóre biblioteki mogą jednak wprowadzać niezgodne zmiany, a ten raport pomoże Ci określić, skąd pochodzą nowe problemy z zachowaniem aplikacji.
Więcej informacji o używaniu raportu zależności Gradle znajdziesz w artykule Wyświetlanie i debugowanie zależności.
Wymagane wersje można określić bezpośrednio w katalogu wersji lub w zestawie specyfikacji materiałów (BOM).
Rozwiązanie problemu z specyfikacją wersji bezpośredniej
Określone przez Ciebie wersje zależności stają się kandydatami do rozwiązania wersji.
Aby na przykład zażądać wersji 1.7.3 biblioteki androidx.compose.ui:ui
jako zależności w bibliotece app/build.gradle.kts
:
dependencies {
implementation("androidx.compose.ui:ui:1.7.3")
}
Wersja 1.7.3 staje się wersją kandydującą. Gradle przekształca się w najnowszą wersję (1.7.3) lub inną wersję tej samej biblioteki, o którą poproszono w ramach zależności cząstkowych.
Rozdzielczość katalogu wersji
Katalogi wersji definiują zmienne służące do śledzenia wersji zależności używanych w aplikacji. Jeśli używasz zmiennej z katalogu wersji, określone przez nią zależności są dodawane do kandydatów do rozwiązania wersji. Nieużywane zmienne w katalogu wersji są ignorowane.
Aby na przykład określić wersję 1.7.3 pakietu androidx.compose.ui:ui
jako zależność w pliku gradle/libs.versions.toml
:
[versions]
ui = "1.7.3"
[libraries]
androidx-compose-ui = { group = "androidx.compose.ui", name = "ui", version.ref = "ui" }
Definiuje zmienną o nazwie libs.androidx.compose.ui
, która reprezentuje bibliotekę. Ta wersja nie jest uważana za kandydata, chyba że użyjesz tej zmiennej do określenia zależności.
Aby poprosić o bibliotekę i jej wersję w app/build.gradle.kts
:
dependencies {
implementation(libs.androidx.compose.ui)
}
Gradle rozwiązuje je w taki sam sposób jak specyfikację bezpośrednią.
Rozdzielczość listy materiałów (BOM)
Wersje wszystkich bibliotek wymienionych w pliku BOM stają się kandydatami do rozwiązania wersji. Pamiętaj, że biblioteki są używane jako zależności tylko wtedy, gdy są określone jako bezpośrednie lub pośrednie. Inne biblioteki w pliku BOM są ignorowane.
Wersje pliku BOM wpływają na bezpośrednie zależności oraz wszystkie pośrednie zależności, które się w nim znajdują.
Na przykład w app/build.gradle.kts
możesz określić plik BOM jako zależność platformy:
dependencies {
implementation(platform("androidx.compose:compose-bom:2024.10.00"))
implementation("androidx.compose.ui:ui")
}
Biblioteki, których chcesz używać jako zależności, nie wymagają specyfikacji wersji. Wymagana wersja pochodzi z pliku BOM.
Pamiętaj, że możesz też użyć katalogu wersji do utworzenia zmiennych dla listy materiałów i bibliotek. Pomiń numery wersji w katalogu wersji bibliotek, które pojawiają się w zależności pliku BOM.
Na przykład katalog wersji zawiera plik BOM i jego numer wersji, ale nie określa wersji bibliotek, do których odwołuje się plik BOM:
[versions]
composeBom = "2024.10.00"
[libraries]
androidx-compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = "composeBom" }
androidx-compose-ui = { group = "androidx.compose.ui", name = "ui" }
Twoja wersja app/build.gradle.kts
odwołuje się do pliku BOM i bibliotek za pomocą zmiennych zdefiniowanych w katalogu wersji:
dependencies {
implementation(platform(libs.androidx.compose.bom))
implementation(libs.androidx.compose.ui)
}
Wersja tej biblioteki określona w pliku BOM staje się kandydatem do rozwiązania przez Gradle. Ponadto wszystkie inne wersje biblioteki określone w pliku BOM stają się wersjami docelowymi, niezależnie od tego, czy używasz ich bezpośrednio jako zależności.
Załóżmy na przykład, że plik BOM określa wersje bibliotek A, B i C. Twoja aplikacja chce bezpośrednio używać biblioteki A jako zależności, a także biblioteki D. Biblioteka D używa biblioteki B jako zależności. Żadna klasa nie używa biblioteki C.
Biblioteki A, B i D są zależnościami w aplikacji; biblioteka C jest ignorowana. Gradle używa wersji A i B określonych w pliku BOM jako kandydatów, mimo że nie określasz bezpośrednio biblioteki B jako zależności.
Jeśli biblioteka D poprosiła o wersję biblioteki B niższą niż 2.0.1, Gradle przekształci ją w 2.0.1. Jeśli biblioteka D poprosiła o wyższą wersję biblioteki B, Gradle przekształca ją w tą wersję.