如果我有模块A和模块B都需要JSON库(比如GSON), 然后我有应用程序C,其中包括模块A& B.如果模块A和B使用不同的版本,我有可能获得两个不同版本的JSON库吗?或者gradle删除其中一个并只使用其中一个版本?
如果我有更多的模块,更新它们以使用相同版本的依赖项似乎需要做很多工作。在这种情况下,让应用程序C决定在所有模块上使用哪个版本会很好(但由于向后兼容性,我猜不总是正常工作)。无论如何要实现这个目标?
所以我的问题是如何最好地处理在许多模块中非常常见的依赖关系。我是否应该在我的所有模块中注入一个Json包装器,让应用程序定义要使用的内容?
我猜日志记录可能是一个类似的依赖
答案 0 :(得分:2)
是。如果您在项目A和B中特别要求提供相同库的不同版本,则最终可能会得到相同直接依赖项的不同版本。
对于瞬态依赖性,默认行为是确定所请求依赖项的最新版本。请注意最新一词,而不是要求的最高版本。只要版本向后兼容项目实际预期的最低版本,就可以了。
幸运的是,gradle有几种内置方法来解决依赖冲突。
我在这里写了很多关于这个主题的文章:http://www.devsbedevin.com/android-understanding-gradle-dependencies-and-resolving-conflicts/
您可以选择在冲突中失败:
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()
}
}
将所有libary 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
}
}
答案 1 :(得分:0)
考虑具有两个模块/项目的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