Debugowanie błędów rozwiązywania zależności

Podczas dodawania zależności mogą wystąpić problemy z wymaganymi zależnościami w oparciu o pierwotną zależność i powodują konflikty między różnymi wersjami zależności. Poniżej znajdziesz informacje o tym, jak przeanalizować graf zależności i rozwiązać typowe problemy.

Wskazówki dotyczące naprawiania błędów związanych z rozwiązywaniem zależności, które obejmują kompilację niestandardową logiki logicznej, zobacz Niestandardowe strategie rozwiązywania problemów z zależnościami.

Wyświetl zależności modułu

Niektóre bezpośrednie zależności mogą mieć własne zależności. Są to tzw. zależności przejściowe. Zamiast wymagać ręcznego deklarowania każdego tagu zależność przejściowa, Gradle automatycznie je zbiera i dodaje. Wtyczka Androida do Gradle udostępnia zadanie, które wyświetla listę które rozwiązuje Gradle w przypadku danego modułu.

Raport w każdym module grupuje też zależności na podstawie wariantu kompilacji, testowego zbioru źródeł classpath. Poniżej znajdziesz przykładowy raport dotyczący czasu działania modułu aplikacji ścieżka klasy jego wariantu kompilacji do debugowania i skompiluj ścieżkę klasy jej ścieżki instrumentacji, testowym zestawem źródeł źródłowych.

debugRuntimeClasspath - Dependencies for runtime/packaging
+--- :mylibrary (variant: debug)
+--- com.google.android.material:material:1.0.0@aar
+--- androidx.appcompat:appcompat:1.0.2@aar
+--- androidx.constraintlayout:constraintlayout:1.1.3@aar
+--- androidx.fragment:fragment:1.0.0@aar
+--- androidx.vectordrawable:vectordrawable-animated:1.0.0@aar
+--- androidx.recyclerview:recyclerview:1.0.0@aar
+--- androidx.legacy:legacy-support-core-ui:1.0.0@aar
...

debugAndroidTest
debugAndroidTestCompileClasspath - Dependencies for compilation
+--- androidx.test.ext:junit:1.1.0@aar
+--- androidx.test.espresso:espresso-core:3.1.1@aar
+--- androidx.test:runner:1.1.1@aar
+--- junit:junit:4.12@jar
...

Aby uruchomić zadanie, wykonaj te czynności:

  1. Wybierz Widok > Okna narzędziowe > Gradle (lub kliknij Gradle na pasku okien narzędzi).
  2. Rozwiń sekcję AppName > Lista zadań > android i kliknij dwukrotnie androidDependencies. Po uruchomieniu Gradle powinno się otworzyć okno Uruchom, aby wyświetlić dane wyjściowe.

Więcej informacji o zarządzaniu zależnościami w Gradle znajdziesz w artykule Podstawowe informacje o zarządzaniu zależnościami w przewodniku użytkownika Gradle.

Wyklucz zależności pośrednie

W miarę rozwoju aplikacji może zawierać szereg zależności, w tym: zależności bezpośrednie i pośrednie (biblioteki, między importowanymi bibliotekami). Aby wykluczyć pośrednie zależności, których już nie potrzebujesz, możesz użyć funkcji exclude słowo kluczowe podane poniżej:

Kotlin

dependencies {
    implementation("some-library") {
        exclude(group = "com.example.imgtools", module = "native")
    }
}

Odlotowe

dependencies {
    implementation('some-library') {
        exclude group: 'com.example.imgtools', module: 'native'
    }
}

Wyklucz zależności pośrednie z konfiguracji testów

Jeśli chcesz wykluczyć z testów określone zależności pośrednie, powyższy przykładowy kod może nie działać zgodnie z oczekiwaniami. To dlatego, że test konfiguracji (np. androidTestImplementation) powoduje rozszerzenie modułu Konfiguracja implementation. Oznacza to, że zawsze zawiera ona ciąg implementation gdy Gradle rozwiązuje konfigurację.

Aby wykluczyć z testów zależności pośrednie, musisz to zrobić na stronie czas wykonania, jak poniżej:

Kotlin

android.testVariants.all {
    compileConfiguration.exclude(group = "com.jakewharton.threetenabp", module = "threetenabp")
    runtimeConfiguration.exclude(group = "com.jakewharton.threetenabp", module = "threetenabp")
}

Odlotowe

android.testVariants.all { variant ->
    variant.getCompileConfiguration().exclude group: 'com.jakewharton.threetenabp', module: 'threetenabp'
    variant.getRuntimeConfiguration().exclude group: 'com.jakewharton.threetenabp', module: 'threetenabp'
}

Uwaga: nadal możesz używać słowa kluczowego exclude. w bloku zależności zgodnie z oryginalnym przykładowym kodem Wyklucz zależności pośrednie aby pominąć zależności przejściowe, które są specyficzne dla testu i nie są uwzględniane w innych konfiguracjach.

Naprawianie błędów związanych z rozwiązywaniem zależności

Gdy dodasz do projektu aplikacji wiele zależności, pośrednie zależności mogą ze sobą kolidować. Gradle Androida próbuje bezproblemowo rozwiązać te konflikty, ale niektóre konflikty mogą kompilować błędy czasu lub czasu działania.

Aby dowiedzieć się, które zależności przyczyniają się do powstawania błędów, sprawdź drzewo zależności aplikacji i wyszukaj które występują więcej niż raz lub mają wersje powodujące konflikty.

Jeśli nie możesz łatwo zidentyfikować zduplikowanej zależności, spróbuj użyć Androida interfejsu użytkownika Studio do wyszukiwania zależności zawierających zduplikowaną klasę; w następujący sposób:

  1. Wybierz Nawigacja > Zajęcia na pasku menu.
  2. Upewnij się, że w wyskakującym okienku wyszukiwania pole obok Opcja Uwzględnij elementy niebędące projektami jest zaznaczona.
  3. Wpisz nazwę klasy, która pojawi się w komunikacie o błędzie kompilacji.
  4. Sprawdź wyniki pod kątem zależności, które obejmują klasę.

W poniższych sekcjach opisano różne typy rozwiązywania zależności możliwych błędów i sposobów ich naprawy.

Naprawianie błędów związanych z duplikatami zajęć

Jeśli w ścieżce środowiska wykonawczego klasa występuje więcej niż raz, otrzymasz podobny do tego:

Program type already present com.example.MyClass

Ten błąd występuje zwykle w jednej z tych przyczyn:

  • Zależność binarna obejmuje bibliotekę, którą aplikacja zawiera jako zależności bezpośredniej. Na przykład aplikacja deklaruje bezpośrednią zależność od Biblioteka A i B, ale Biblioteka A obejmuje już Bibliotekę B binarny.
    • Aby rozwiązać ten problem, usuń Bibliotekę B jako zależność bezpośrednią.
  • Aplikacja ma lokalną zależność binarną oraz zdalną zależność binarną w tej samej bibliotece.
    • Aby rozwiązać ten problem, usuń jedną z zależności binarnych.

Rozwiązywanie konfliktów między ścieżkami zajęć

Gdy Gradle rozpozna ścieżkę klasy kompilacji, najpierw rozstrzygnie środowisko wykonawcze classpath i używa wyniku do określenia, które wersje zależności powinny być zostaną dodane do ścieżki klasy kompilacji. Innymi słowy, środowisko wykonawcze classpath określa wymagane numery wersji dla identycznych zależności ścieżek klasowych.

Ścieżka klasy środowiska wykonawczego aplikacji określa też numery wersji, które Gradle wymaga dopasowania zależności w ścieżce klasy środowiska wykonawczego na potrzeby testu aplikacji plik APK. Hierarchia ścieżek klas została opisana na rysunku 1.

Rysunek 1. Numery wersji zależności które występują w wielu ścieżkach zajęć, muszą pasować zgodnie z tym w hierarchii.

Konflikt, w którym występują różne wersje tej samej zależności wiele ścieżek klas może wystąpić, gdy na przykład aplikacja zawiera wersję zależność z użyciem funkcji implementation konfiguracja zależności a moduł biblioteki zawiera inną wersję zależności Konfiguracja runtimeOnly.

Podczas rozwiązywania zależności od środowiska wykonawczego i kompilowania ścieżek klas czasowych, Android Wtyczka Gradle w wersji 3.3.0 lub nowszej próbuje automatycznie naprawić niektóre z kolejnych żądań i konflikty wersji. Jeśli na przykład ścieżka klasy środowiska wykonawczego zawiera Bibliotekę A 2.0, a ścieżka klasy kompilacji zawiera Bibliotekę A w wersji 1.0, automatycznie aktualizuje zależność w ścieżce klasy kompilacji do biblioteki A wersji 2.0, by uniknąć błędów.

Jeśli jednak ścieżka klasy środowiska wykonawczego zawiera bibliotekę A w wersji 1.0 i narzędzie classpath obejmuje Bibliotekę A w wersji 2.0, wtyczka nie zmienia w bibliotece A w wersji 1.0, a mimo to podobny błąd:

Conflict with dependency 'com.example.library:some-lib:2.0' in project 'my-library'.
Resolved versions for runtime classpath (1.0) and compile classpath (2.0) differ.

Aby rozwiązać ten problem, wykonaj jedną z tych czynności:

  • Uwzględnij żądaną wersję zależności jako zależność api w elemencie z biblioteki. Oznacza to, że tylko moduł biblioteki deklaruje zależność, moduł aplikacji będzie też pośrednio korzystać ze swojego interfejsu API.
  • Możesz też zadeklarować zależność w obu modułach, ale sprawdź, czy każdy moduł używa tej samej wersji zależności. Rozważ konfigurowanie właściwości na poziomie projektu aby wersje każdej zależności były spójne w całym projekcie.