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 elementy minor
(nowe funkcje) lub patch
(poprawki błędów) ulegną zmianie, biblioteka prawdopodobnie będzie nadal zgodna, a prawdopodobieństwo nie będzie miało wpływu na Twoją aplikację.
Załóżmy na przykład, że Twoja aplikacja zależy od biblioteki A i biblioteki B, które z kolei zależą 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 uruchamianiem. W tym przykładzie biblioteka C ma postać 2.1.1, ale biblioteka A zażądała biblioteki C 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ę, o którą prosisz bezpośrednio 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 bardziej zaawansowanych narzędzi. 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. W przypadku aplikacji, która korzysta z bibliotek przedstawionych na rysunku 2, widzimy
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 korzystaniu z raportowania zależności Gradle znajdziesz w artykule Wyświetlanie i debugowanie zależności.
Żądane wersje możesz określić bezpośrednio w katalogu wersji lub w liście materiałów (BOM).
Rozwiązanie bezpośredniej specyfikacji wersji
Wskazane przez Ciebie wersje zależności stają się kandydatami do rozpoznawania 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 przestaje działać do najnowszej wersji wśród 1.7.3 i innych wersji tej samej biblioteki, których żądają zależności przechodnie.
Rozwiązanie 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 np. określić wersję 1.7.3 elementu 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 to zmienną o nazwie libs.androidx.compose.ui
reprezentującą bibliotekę. Ta wersja nie jest uznawana za kandydującą, 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 działa w taki sam sposób jak w przypadku specyfikacji bezpośredniej.
Rozdzielczość listy materiałów (BOM)
Wersje wszystkich bibliotek widocznych w BOM stają się kandydatami do rozpoznania wersji. Pamiętaj, że biblioteki są używane jako zależności tylko wtedy, gdy zostały określone jako bezpośrednie lub pośrednie. Pozostałe biblioteki w BOM są ignorowane.
Wersje BOM wpływają na zależności bezpośrednie, a także na wszystkie zależności pośrednie występujące w BOM.
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 BOM i jego numer wersji, ale nie określa wersji dla bibliotek, do których się odwołujesz z 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" }
Plik app/build.gradle.kts
odwołuje się do 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 w Gradle. Ponadto wszystkie pozostałe wersje bibliotek określone w BOM stają się wersjami kandydującymi, niezależnie od tego, czy użyjesz ich bezpośrednio jako zależności.
Załóżmy na przykład, że BOM określa wersje bibliotek A, B i C. Twoja aplikacja chce bezpośrednio używać biblioteki A oraz biblioteki D jako zależności. Biblioteka D używa biblioteki B jako zależności. Nic 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 zażądała wyższej wersji biblioteki B, Gradle użyje tej wersji.