模块间的依赖管理
Dependency management between modules
如果我有模块 A 和模块 B,它们都需要一个 JSON 库(比如 GSON),
然后我有包含模块 A 和 B 的应用程序 C。如果模块 A 和 B 使用不同版本,我是否有机会获得 JSON 库的两个不同版本?还是 gradle 删除其中一个并只使用其中一个版本?
如果我有更多模块怎么办,更新它们以使用相同版本的依赖项似乎需要大量工作。在这种情况下,让应用程序 C 决定在所有模块上使用哪个版本会很好(但我猜由于向后兼容性,并不总是有效)。无论如何要实现这个目标?
所以我的问题是如何最好地处理许多模块中非常常见的依赖关系。我是否应该在所有模块中注入一个 Json 包装器,让应用程序定义要使用的内容?
我想日志记录可能是一个类似的依赖关系
是的。如果您在项目 A 和 B 中特别要求同一个库的不同版本,您最终可能会得到同一个直接依赖项的不同版本。
至于临时依赖,默认行为是选择最新版本的请求依赖。请注意最新这个词,而不是请求的最高版本。这很好,只要版本向后兼容您的项目实际期望的最低版本。
幸运的是,gradle 有几个内置的方法来解决依赖冲突。
我在这里写了很多关于这个主题的文章:http://www.devsbedevin.net/android-understanding-gradle-dependencies-and-resolving-conflicts/
TL;DR
您可以选择在冲突时失败:
configurations.all {
resolutionStrategy {
failOnVersionConflict()
}
}
强制特定依赖项:
configurations.all {
resolutionStrategy {
force 'asm:asm-all:3.3.1', 'commons-io:commons-io:1.4', 'com.parse.bolts:bolts-android:1.+'
}
}
更喜欢你自己的模块:
configurations.all {
resolutionStrategy {
preferProjectModules()
}
}
将库 X 的所有实例替换为 Y(库、模块或项目):
configurations.all {
resolutionStrategy {
dependencySubstitution {
substitute module('commons-io:commons-io:2.4') with project(':my-commons-io')
}
}
}
排除特定库的所有临时依赖项并手动添加必要的库:
dependencies {
compile('com.android.support:appcompat-v7:23.1.0') {
transitive = false
}
}
排除特定的传递依赖:
dependencies {
compile('com.android.support:appcompat-v7:23.1.0') {
exclude group: 'com.parse.bolts'
}
}
强制您的项目使用特定版本而不考虑实际的依赖要求:
dependencies {
compile('com.parse.bolts:bolts-android:1.+') {
force = true
}
}
考虑具有两个 modules/projects 的 Gradle 构建。 settings.gradle
文件:
include 'modA', 'modB'
假设两者都使用 commons-lang3-3.6
,modA
使用 gson-2.8.1
,而 modB
使用 gson-2.2.4
。可以在根目录的 build.gradle
文件中进行配置:
subprojects { p ->
apply plugin: 'java'
repositories {
jcenter()
}
dependencies {
compile 'org.apache.commons:commons-lang3:3.6'
}
if (p.name == 'modA') {
dependencies {
compile 'com.google.code.gson:gson:2.8.1'
}
} else if (p.name == 'modB') {
dependencies {
compile 'com.google.code.gson:gson:2.2.4'
}
}
}
可以通过以下方式确认所需的配置:
$ gradle :modA:dependencies
$ gradle :modB:dependencies
如果我有模块 A 和模块 B,它们都需要一个 JSON 库(比如 GSON), 然后我有包含模块 A 和 B 的应用程序 C。如果模块 A 和 B 使用不同版本,我是否有机会获得 JSON 库的两个不同版本?还是 gradle 删除其中一个并只使用其中一个版本?
如果我有更多模块怎么办,更新它们以使用相同版本的依赖项似乎需要大量工作。在这种情况下,让应用程序 C 决定在所有模块上使用哪个版本会很好(但我猜由于向后兼容性,并不总是有效)。无论如何要实现这个目标?
所以我的问题是如何最好地处理许多模块中非常常见的依赖关系。我是否应该在所有模块中注入一个 Json 包装器,让应用程序定义要使用的内容?
我想日志记录可能是一个类似的依赖关系
是的。如果您在项目 A 和 B 中特别要求同一个库的不同版本,您最终可能会得到同一个直接依赖项的不同版本。
至于临时依赖,默认行为是选择最新版本的请求依赖。请注意最新这个词,而不是请求的最高版本。这很好,只要版本向后兼容您的项目实际期望的最低版本。
幸运的是,gradle 有几个内置的方法来解决依赖冲突。
我在这里写了很多关于这个主题的文章:http://www.devsbedevin.net/android-understanding-gradle-dependencies-and-resolving-conflicts/
TL;DR
您可以选择在冲突时失败:
configurations.all {
resolutionStrategy {
failOnVersionConflict()
}
}
强制特定依赖项:
configurations.all {
resolutionStrategy {
force 'asm:asm-all:3.3.1', 'commons-io:commons-io:1.4', 'com.parse.bolts:bolts-android:1.+'
}
}
更喜欢你自己的模块:
configurations.all {
resolutionStrategy {
preferProjectModules()
}
}
将库 X 的所有实例替换为 Y(库、模块或项目):
configurations.all {
resolutionStrategy {
dependencySubstitution {
substitute module('commons-io:commons-io:2.4') with project(':my-commons-io')
}
}
}
排除特定库的所有临时依赖项并手动添加必要的库:
dependencies {
compile('com.android.support:appcompat-v7:23.1.0') {
transitive = false
}
}
排除特定的传递依赖:
dependencies {
compile('com.android.support:appcompat-v7:23.1.0') {
exclude group: 'com.parse.bolts'
}
}
强制您的项目使用特定版本而不考虑实际的依赖要求:
dependencies {
compile('com.parse.bolts:bolts-android:1.+') {
force = true
}
}
考虑具有两个 modules/projects 的 Gradle 构建。 settings.gradle
文件:
include 'modA', 'modB'
假设两者都使用 commons-lang3-3.6
,modA
使用 gson-2.8.1
,而 modB
使用 gson-2.2.4
。可以在根目录的 build.gradle
文件中进行配置:
subprojects { p ->
apply plugin: 'java'
repositories {
jcenter()
}
dependencies {
compile 'org.apache.commons:commons-lang3:3.6'
}
if (p.name == 'modA') {
dependencies {
compile 'com.google.code.gson:gson:2.8.1'
}
} else if (p.name == 'modB') {
dependencies {
compile 'com.google.code.gson:gson:2.2.4'
}
}
}
可以通过以下方式确认所需的配置:
$ gradle :modA:dependencies
$ gradle :modB:dependencies