В файлах сборки указаны ваши прямые зависимости, но каждая из этих зависимостей может требовать других. Эти транзитивные зависимости быстро увеличивают общий граф зависимостей, часто с конфликтующими версиями.
При изменении minor
(новых функций) или patch
(исправлений ошибок) частей библиотека, скорее всего, останется совместимой и с меньшей вероятностью повлияет на ваше приложение.
Например, предположим, что ваше приложение зависит от библиотеки A и библиотеки B, которые, в свою очередь, зависят от разных версий библиотеки C.
В этом случае Gradle по умолчанию выбирает новейшую версию библиотеки C, что может вызвать проблемы с компиляцией или выполнением. В этом примере библиотека C разрешается до версии 2.1.1, но обратите внимание, что библиотека A запросила библиотеку C 1.0.3. Большая часть номера версии изменилась, что указывает на несовместимые изменения, такие как удаление функций или типов. Это может привести к сбою вызовов, сделанных из библиотеки A.
Ваше приложение может иметь прямые зависимости, которые также являются транзитивными.
В таком случае новые транзитивные зависимости могут переопределить версию, которую вы напрямую запрашиваете в своем приложении.
Gradle просматривает все версии-кандидаты для всех зависимостей в графе, чтобы определить новейшую версию каждой зависимости. Вы можете использовать базовые задачи Gradle и более продвинутые инструменты, чтобы определить, какие версии каждой зависимости решены Gradle. Сравнение изменений в этом разрешении является ключом к пониманию и снижению рисков вашего обновления.
Например, вы можете использовать задачу dependencies
Gradle, запустив ./gradlew app:dependencies
, чтобы отобразить дерево всех зависимостей, используемых вашим модулем приложения. Запустив это для приложения, использующего библиотеки, как показано на рисунке 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 (*)
В этой части отчета показаны некоторые зависимости, разрешенные для конфигурации releaseRuntimeClasspath
.
Всякий раз, когда вы видите ->
в отчете о зависимостях, запрашивающая сторона (ваше приложение или другая библиотека) использует версию этой зависимости, которую он не ожидает. Во многих случаях это не вызывает никаких проблем, поскольку большинство библиотек написаны с учетом обратной совместимости. Однако некоторые библиотеки могут вносить несовместимые изменения, и этот отчет поможет вам определить, откуда возникают новые проблемы в поведении вашего приложения.
Более подробную информацию об использовании отчетов о зависимостях Gradle можно найти в разделе Просмотр и отладка зависимостей .
Запрошенные версии можно указать напрямую, в каталоге версий или в спецификации (BOM).
Разрешение спецификации прямой версии
Указанные вами версии зависимостей становятся кандидатами на разрешение версий.
Например, чтобы запросить версию 1.7.3 библиотеки androidx.compose.ui:ui
в качестве зависимости в вашем app/build.gradle.kts
:
dependencies {
implementation("androidx.compose.ui:ui:1.7.3")
}
Версия 1.7.3 становится версией-кандидатом. Gradle разрешает последнюю версию среди 1.7.3 и других версий той же библиотеки, запрошенных транзитивными зависимостями.
Разрешение каталога версий
Каталоги версий определяют переменные для отслеживания версий зависимостей, используемых в вашем приложении. Если вы используете переменную из каталога версий, то указанные зависимости этой переменной добавляются к кандидатам на разрешение версии. Неиспользуемые переменные в каталоге версий игнорируются.
Например, чтобы указать версию 1.7.3 файла androidx.compose.ui:ui
в качестве зависимости в файле gradle/libs.versions.toml
:
[versions]
ui = "1.7.3"
[libraries]
androidx-compose-ui = { group = "androidx.compose.ui", name = "ui", version.ref = "ui" }
Здесь определяется переменная с именем libs.androidx.compose.ui
представляющая библиотеку. Эта версия не считается кандидатом, если вы не используете эту переменную для указания зависимости.
Чтобы запросить библиотеку и ее версию в вашем app/build.gradle.kts
:
dependencies {
implementation(libs.androidx.compose.ui)
}
Gradle решает так же, как и для прямой спецификации.
Разрешение спецификации материалов (BOM)
Версии всех библиотек, представленных в спецификации, становятся кандидатами на разрешение версий. Обратите внимание, что библиотеки используются как зависимости, только если они указаны как прямые или косвенные. Другие библиотеки в спецификации игнорируются.
Версии спецификации влияют на ваши прямые зависимости, а также на все транзитивные зависимости, которые появляются в спецификации.
Например, укажите спецификацию в качестве зависимости платформы в вашем app/build.gradle.kts
:
dependencies {
implementation(platform("androidx.compose:compose-bom:2024.10.00"))
implementation("androidx.compose.ui:ui")
}
Любые библиотеки, которые вы хотите использовать в качестве зависимостей, не требуют указания версии; запрошенная версия взята из спецификации.
Обратите внимание, что вы также можете использовать каталог версий для создания переменных для спецификации и библиотек. Опустите номера версий в каталоге версий для библиотек, которые появляются в зависимости от спецификации.
Например, ваш каталог версий содержит спецификацию и номер ее версии, но не указывает версию для библиотек, на которые вы ссылаетесь из спецификации:
[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" }
Ваше app/build.gradle.kts
ссылается на спецификацию и библиотеки, используя переменные, определенные в каталоге версий:
dependencies {
implementation(platform(libs.androidx.compose.bom))
implementation(libs.androidx.compose.ui)
}
Версия этой библиотеки, указанная в спецификации, становится кандидатом на разрешение Gradle. Кроме того, все остальные версии библиотек, указанные в спецификации, становятся версиями-кандидатами, независимо от того, используете ли вы их напрямую в качестве зависимостей.
Например, предположим, что в спецификации указаны версии библиотек A, B и C. Ваше приложение хочет напрямую использовать библиотеку A в качестве зависимости, а также библиотеку D. Библиотека D использует библиотеку B в качестве зависимости. Ничто не использует библиотеку C.
Библиотеки A, B и D являются зависимостями приложения; библиотека C игнорируется. Gradle использует версии A и B, указанные в спецификации, в качестве кандидатов, даже если вы не указываете библиотеку B напрямую в качестве зависимости.
Если библиотека D запросила версию библиотеки B ниже 2.0.1, Gradle разрешит версию 2.0.1. Если библиотека D запросила более позднюю версию библиотеки B, Gradle разрешит эту версию.