http://www.paincker.com/gradle-dependencies

https://docs.gradle.org/current/userguide/dependency_management.html

http://www.concretepage.com/build-tools/gradle/gradle-exclude-transitive-dependency-example

Gradle是一个非常好用的编译工具,特别是继承了maven的依赖项管理功能,需要的Library不需要像传统IDE一样手动下载复制到项目中,只需要简单的写一行gradle脚本,就能自动下载下来并编译。

但是有时候会出现各种不明情况的报错,最常见的一种原因就是依赖项版本冲突。

每个模块都可能依赖其他模块,这些模块又会依赖别的模块。而一个项目中的多个模块,对同一个模块的不同版本有依赖,就可能产生冲突。

通过gradle命令查看依赖树,可以比较直观的看到冲突。具体方法是在模块所在的目录,也即build.gradle所在目录下执行gradle dependencies(需要将gradle加入PATH环境变量),执行结果如图。

Transitive

Transitive用于自动处理子依赖项。默认为true,gradle自动添加子依赖项,形成一个多层树形结构;设置为false,则需要手动添加每个依赖项。

案例

以安卓单元测试espresso的配置为例,gradle依赖如下:

  1. dependencies {
  2. androidTestCompile('com.android.support.test:runner:0.2')
  3. androidTestCompile('com.android.support.test:rules:0.2')
  4. androidTestCompile('com.android.support.test.espresso:espresso-core:2.1')
  5. }

运行gradle dependencies的结果如下。可以看到每个包的依赖项都被递归分析并添加进来。

  1. +--- com.android.support.test:runner:0.2
  2. | +--- junit:junit-dep:4.10
  3. | | \--- org.hamcrest:hamcrest-core:1.1
  4. | +--- com.android.support.test:exposed-instrumentation-api-publish:0.2
  5. | \--- com.android.support:support-annotations:22.0.0
  6. +--- com.android.support.test:rules:0.2
  7. | \--- com.android.support.test:runner:0.2 (*)
  8. \--- com.android.support.test.espresso:espresso-core:2.1
  9. +--- com.android.support.test:rules:0.2 (*)
  10. +--- com.squareup:javawriter:2.1.1
  11. +--- org.hamcrest:hamcrest-integration:1.1
  12. | \--- org.hamcrest:hamcrest-core:1.1
  13. +--- com.android.support.test.espresso:espresso-idling-resource:2.1
  14. +--- org.hamcrest:hamcrest-library:1.1
  15. | \--- org.hamcrest:hamcrest-core:1.1
  16. +--- javax.inject:javax.inject:1
  17. +--- com.google.code.findbugs:jsr305:2.0.1
  18. +--- com.android.support.test:runner:0.2 (*)
  19. +--- javax.annotation:javax.annotation-api:1.2
  20. \--- org.hamcrest:hamcrest-core:1.1

统一指定transitive

可以给dependencies统一指定transitive为false,再次执行dependencies可以看到如下结果。

  1. configurations.all {
  2. transitive = false
  3. }
  4. dependencies {
  5. androidTestCompile('com.android.support.test:runner:0.2')
  6. androidTestCompile('com.android.support.test:rules:0.2')
  7. androidTestCompile('com.android.support.test.espresso:espresso-core:2.1')
  8. }
  1. +--- com.android.support.test:runner:0.2
  2. +--- com.android.support.test:rules:0.2
  3. \--- com.android.support.test.espresso:espresso-core:2.1

单独指定依赖项的transitive

  1. dependencies {
  2. androidTestCompile('com.android.support.test:runner:0.2')
  3. androidTestCompile('com.android.support.test:rules:0.2')
  4. androidTestCompile('com.android.support.test.espresso:espresso-core:2.1') {
  5. transitive = false
  6. }
  7. }

版本冲突

在同一个配置下(例如androidTestCompile),某个模块的不同版本同时被依赖时,默认使用最新版,gradle同步时不会报错。例如下面的hamcrest-core和runner。

  1. dependencies {
  2. androidTestCompile('com.android.support.test:runner:0.4')
  3. androidTestCompile('com.android.support.test:rules:0.2')
  4. androidTestCompile('com.android.support.test.espresso:espresso-core:2.1')
  5. }
  1. +--- com.android.support.test:runner:0.4
  2. | +--- com.android.support:support-annotations:23.0.1
  3. | +--- junit:junit:4.12
  4. | | \--- org.hamcrest:hamcrest-core:1.3
  5. | \--- com.android.support.test:exposed-instrumentation-api-publish:0.4
  6. +--- com.android.support.test:rules:0.2
  7. | \--- com.android.support.test:runner:0.2 -> 0.4 (*)
  8. \--- com.android.support.test.espresso:espresso-core:2.1
  9. +--- com.android.support.test:rules:0.2 (*)
  10. +--- com.squareup:javawriter:2.1.1
  11. +--- org.hamcrest:hamcrest-integration:1.1
  12. | \--- org.hamcrest:hamcrest-core:1.1 -> 1.3
  13. +--- com.android.support.test.espresso:espresso-idling-resource:2.1
  14. +--- org.hamcrest:hamcrest-library:1.1
  15. | \--- org.hamcrest:hamcrest-core:1.1 -> 1.3
  16. +--- javax.inject:javax.inject:1
  17. +--- com.google.code.findbugs:jsr305:2.0.1
  18. +--- com.android.support.test:runner:0.2 -> 0.4 (*)
  19. +--- javax.annotation:javax.annotation-api:1.2
  20. \--- org.hamcrest:hamcrest-core:1.1 -> 1.3

Force

force强制设置某个模块的版本。

  1. configurations.all {
  2. resolutionStrategy {
  3. force 'org.hamcrest:hamcrest-core:1.3'
  4. }
  5. }
  6. dependencies {
  7. androidTestCompile('com.android.support.test:runner:0.2')
  8. androidTestCompile('com.android.support.test:rules:0.2')
  9. androidTestCompile('com.android.support.test.espresso:espresso-core:2.1')
  10. }

可以看到,原本对hamcrest-core 1.1的依赖,全部变成了1.3。

  1. +--- com.android.support.test:runner:0.2
  2. | +--- junit:junit-dep:4.10
  3. | | \--- org.hamcrest:hamcrest-core:1.1 -> 1.3
  4. | +--- com.android.support.test:exposed-instrumentation-api-publish:0.2
  5. | \--- com.android.support:support-annotations:22.0.0
  6. +--- com.android.support.test:rules:0.2
  7. | \--- com.android.support.test:runner:0.2 (*)
  8. \--- com.android.support.test.espresso:espresso-core:2.1
  9. +--- com.android.support.test:rules:0.2 (*)
  10. +--- com.squareup:javawriter:2.1.1
  11. +--- org.hamcrest:hamcrest-integration:1.1
  12. | \--- org.hamcrest:hamcrest-core:1.1 -> 1.3
  13. +--- com.android.support.test.espresso:espresso-idling-resource:2.1
  14. +--- org.hamcrest:hamcrest-library:1.1
  15. | \--- org.hamcrest:hamcrest-core:1.1 -> 1.3
  16. +--- javax.inject:javax.inject:1
  17. +--- com.google.code.findbugs:jsr305:2.0.1
  18. +--- com.android.support.test:runner:0.2 (*)
  19. +--- javax.annotation:javax.annotation-api:1.2
  20. \--- org.hamcrest:hamcrest-core:1.1 -> 1.3

Exclude

Exclude可以设置不编译指定的模块

  1. configurations {
  2. all*.exclude group: 'org.hamcrest', module: 'hamcrest-core'
  3. }
  4. dependencies {
  5. androidTestCompile('com.android.support.test:runner:0.2')
  6. androidTestCompile('com.android.support.test:rules:0.2')
  7. androidTestCompile('com.android.support.test.espresso:espresso-core:2.1')
  8. }
  1. +--- com.android.support.test:runner:0.2
  2. | +--- junit:junit-dep:4.10
  3. | +--- com.android.support.test:exposed-instrumentation-api-publish:0.2
  4. | \--- com.android.support:support-annotations:22.0.0
  5. +--- com.android.support.test:rules:0.2
  6. | \--- com.android.support.test:runner:0.2 (*)
  7. \--- com.android.support.test.espresso:espresso-core:2.1
  8. +--- com.android.support.test:rules:0.2 (*)
  9. +--- com.squareup:javawriter:2.1.1
  10. +--- org.hamcrest:hamcrest-integration:1.1
  11. +--- com.android.support.test.espresso:espresso-idling-resource:2.1
  12. +--- org.hamcrest:hamcrest-library:1.1
  13. +--- javax.inject:javax.inject:1
  14. +--- com.google.code.findbugs:jsr305:2.0.1
  15. +--- com.android.support.test:runner:0.2 (*)
  16. \--- javax.annotation:javax.annotation-api:1.2

单独使用group或module参数

exclude后的参数有group和module,可以分别单独使用,会排除所有匹配项。例如下面的脚本匹配了所有的group为’com.android.support.test’的模块。

  1. configurations {
  2. all*.exclude group: 'com.android.support.test'
  3. }
  4. dependencies {
  5. androidTestCompile('com.android.support.test:runner:0.2')
  6. androidTestCompile('com.android.support.test:rules:0.2')
  7. androidTestCompile('com.android.support.test.espresso:espresso-core:2.1')
  8. }
  1. \--- com.android.support.test.espresso:espresso-core:2.1
  2. +--- com.squareup:javawriter:2.1.1
  3. +--- org.hamcrest:hamcrest-integration:1.1
  4. | \--- org.hamcrest:hamcrest-core:1.1
  5. +--- com.android.support.test.espresso:espresso-idling-resource:2.1
  6. +--- org.hamcrest:hamcrest-library:1.1
  7. | \--- org.hamcrest:hamcrest-core:1.1
  8. +--- javax.inject:javax.inject:1
  9. +--- com.google.code.findbugs:jsr305:2.0.1
  10. +--- javax.annotation:javax.annotation-api:1.2
  11. \--- org.hamcrest:hamcrest-core:1.1

单独给某个模块指定exclude

  1. dependencies {
  2. androidTestCompile('com.android.support.test:runner:0.2')
  3. androidTestCompile('com.android.support.test:rules:0.2')
  4. androidTestCompile('com.android.support.test.espresso:espresso-core:2.1') {
  5. exclude group: 'org.hamcrest'
  6. }
  7. }
  1. +--- com.android.support.test:runner:0.2
  2. | +--- junit:junit-dep:4.10
  3. | | \--- org.hamcrest:hamcrest-core:1.1
  4. | +--- com.android.support.test:exposed-instrumentation-api-publish:0.2
  5. | \--- com.android.support:support-annotations:22.0.0
  6. +--- com.android.support.test:rules:0.2
  7. | \--- com.android.support.test:runner:0.2 (*)
  8. \--- com.android.support.test.espresso:espresso-core:2.1
  9. +--- com.android.support.test:rules:0.2 (*)
  10. +--- com.squareup:javawriter:2.1.1
  11. +--- com.android.support.test.espresso:espresso-idling-resource:2.1
  12. +--- javax.inject:javax.inject:1
  13. +--- com.google.code.findbugs:jsr305:2.0.1
  14. +--- com.android.support.test:runner:0.2 (*)
  15. \--- javax.annotation:javax.annotation-api:1.2

不同配置下的版本冲突

同样的配置下的版本冲突,会自动使用最新版;而不同配置下的版本冲突,gradle同步时会直接报错。可使用exclude、force解决冲突。

例如compile 'com.android.support:appcompat-v7:23.1.1',和androidTestCompile 'com.android.support.test.espresso:espresso-core:2.1',所依赖的com.android.support:support-annotations版本不同,就会导致冲突。

  1. dependencies {
  2. compile 'com.android.support:appcompat-v7:23.1.1'
  3. androidTestCompile('com.android.support.test:runner:0.2')
  4. androidTestCompile('com.android.support.test:rules:0.2')
  5. androidTestCompile('com.android.support.test.espresso:espresso-core:2.1')
  6. }

gradle同步时会提示

  1. Warning:Conflict with dependency 'com.android.support:support-annotations'. Resolved versions for app and test app differ.

执行dependencies会提示

  1. FAILURE: Build failed with an exception.
  2. * What went wrong:
  3. A problem occurred configuring project ':app'.
  4. > Conflict with dependency 'com.android.support:support-annotations'. Resolved versions for app and test app differ.
  5. * Try:
  6. Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.
  7. BUILD FAILED

不兼容

虽然可以通过force、exclude等方式避免依赖项版本冲突,使得grade同步成功,但是并不能代表编译时没有问题。由于不同版本可能不完全兼容,于是会出现各种奇怪的报错。已知的解决思路是更改包的版本、尝试强制使用不同版本的依赖项,找到可兼容的依赖组合。

报错例如:

  1. com.android.dex.DexException: Multiple dex files define Lorg/hamcrest/MatcherAssert;
  2. at com.android.dx.merge.DexMerger.readSortableTypes(DexMerger.java:596)
  3. at com.android.dx.merge.DexMerger.getSortedTypes(DexMerger.java:554)
  4. at com.android.dx.merge.DexMerger.mergeClassDefs(DexMerger.java:535)
  5. at com.android.dx.merge.DexMerger.mergeDexes(DexMerger.java:171)
  6. at com.android.dx.merge.DexMerger.merge(DexMerger.java:189)
  7. at com.android.dx.command.dexer.Main.mergeLibraryDexBuffers(Main.java:454)
  8. at com.android.dx.command.dexer.Main.runMonoDex(Main.java:303)
  9. at com.android.dx.command.dexer.Main.run(Main.java:246)
  10. at com.android.dx.command.dexer.Main.main(Main.java:215)
  11. at com.android.dx.command.Main.main(Main.java:106)
  12. Error:Execution failed for task ':app:dexDebugAndroidTest'.
  13. > com.android.ide.common.process.ProcessException: org.gradle.process.internal.ExecException: Process 'command '/Library/Java/JavaVirtualMachines/jdk1.8.0_40.jdk/Contents/Home/bin/java'' finished with non-zero exit value 2
  14. BUILD FAILED

又例如Android执行Espresso单元测试时出现:

  1. Running tests
  2. Test running started
  3. java.lang.NoSuchMethodError: org.hamcrest.core.AnyOf.anyOf
  4. at org.hamcrest.Matchers.anyOf(Matchers.java:87)
  5. at android.support.test.espresso.Espresso.<clinit>(Espresso.java:158)
  6. at com.jzj1993.unittest.test.MainActivityEspressoTest.sayHello(MainActivityEspressoTest.java:28)
  7. at java.lang.reflect.Method.invokeNative(Native Method)
  8. at java.lang.reflect.Method.invoke(Method.java:525)
  9. at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:45)
  10. at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
  11. at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:42)
  12. at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
  13. at android.support.test.internal.statement.UiThreadStatement.evaluate(UiThreadStatement.java:55)
  14. at android.support.test.rule.ActivityTestRule$ActivityStatement.evaluate(ActivityTestRule.java:257)
  15. at org.junit.rules.RunRules.evaluate(RunRules.java:18)
  16. at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:263)
  17. at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:68)
  18. at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:47)
  19. at org.junit.runners.ParentRunner$3.run(ParentRunner.java:231)
  20. at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60)
  21. at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229)
  22. at org.junit.runners.ParentRunner.access$000(ParentRunner.java:50)
  23. at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222)
  24. at org.junit.runners.ParentRunner.run(ParentRunner.java:300)
  25. at org.junit.runners.Suite.runChild(Suite.java:128)
  26. at org.junit.runners.Suite.runChild(Suite.java:24)
  27. at org.junit.runners.ParentRunner$3.run(ParentRunner.java:231)
  28. at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60)
  29. at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229)
  30. at org.junit.runners.ParentRunner.access$000(ParentRunner.java:50)
  31. at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222)
  32. at org.junit.runners.ParentRunner.run(ParentRunner.java:300)
  33. at org.junit.runner.JUnitCore.run(JUnitCore.java:157)
  34. at org.junit.runner.JUnitCore.run(JUnitCore.java:136)
  35. at android.support.test.internal.runner.TestExecutor.execute(TestExecutor.java:54)
  36. at android.support.test.runner.AndroidJUnitRunner.onStart(AndroidJUnitRunner.java:228)
  37. at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:1701)
  38. Finish

参考资料与扩展阅读

https://docs.gradle.org/current/userguide/dependency_management.html
http://www.concretepage.com/build-tools/gradle/gradle-exclude-transitive-dependency-example

Gradle依赖项学习总结,dependencies、transitive、force、exclude的使用与依赖冲突解决的更多相关文章

  1. “未能加载文件或程序集“XXX”或它的某一个依赖项。试图加载格式不正确的程序”问题的解决

    发布到win7 64位旗舰版iis上时,报:“未能加载文件或程序集“BC.Common”或它的某一个依赖项.试图加载格式不正确的程序”. 该DLL的本地复制没有设置为true(在项目引用里找到该引用, ...

  2. 学习WPF——初识依赖项属性

    入门 首先创建一个依赖项属性 然后绑定父容器的DataContext到这个依赖项的实例 接着绑定子元素的属性到依赖项属性(注意Button的Content属性) 程序最终的运行结果:   说明 首先是 ...

  3. WPF中的依赖项属性

    Form cnblogs 桂素伟 随着WPF的推广,不得不重新拾起WPF来,因为这块的产品越来越多. 只能跟着MSDN来学了,所以想是在这里记录下学习的过程和对知识的理解. 先从最基本的吧,依赖项属性 ...

  4. WPF中的依赖项属性(转)

    出处:https://www.cnblogs.com/axzxs2001/archive/2010/04/25/1719857.html 随着WPF的推广,不得不重新拾起WPF来,因为这块的产品越来越 ...

  5. WPF教程五:附加依赖项属性

    附加依赖项属性是一个属性本来不属于对象自己,但是某些特定场景其他的对象要使用该对象在这种场景下的值.这个值只在这个场景下使用.基于这个需求设计出来的属性.这里主要涉及到一个解耦问题.最大的优势是在特定 ...

  6. 未能加载文件或程序集“System.Web.Http.WebHost, Version=4.0.0.0, ”或它的某一个依赖项。系统找不到指定的文件。

    一:错误提示 "未能加载文件或程序集"System.Web.Http.WebHost, Version=4.0.0.0, Culture=neutral, PublicKeyTok ...

  7. 安装SQL2008时遇到"未能加载文件或"file:///d:microsoft..sql.chainer.packagedata.dll"或它的某个依赖项

    安装SQL2008时遇到"未能加载文件或"file:///d:microsoft..sql.chainer.packagedata.dll"或它的某个依赖项,如下图所示 ...

  8. 浅谈WPF依赖项属性

    浅谈WPF依赖项属性 0. 引言 依赖项属性虽然在使用上和CLR属性一样,但是它是WPF特有的,不同于CLR属性.只是封装为我们常用CLR的属性,在语法使用上和CLR属性一样.WPF中一些功能:动画, ...

  9. .NET Core TDD 前传: 编写易于测试的代码 -- 依赖项

    第1篇: 讲述了如何创造"缝".  "缝"(seam)是需要知道的概念. 第2篇, 避免在构建对象时写出不易测试的代码. 本文是第3篇, 讲述依赖项和迪米特法则 ...

随机推荐

  1. c#抓取网页内容乱码的解决方案

    写过爬虫的同学都知道,这是个很常见的问题了,一般处理思路是: 使用HttpWebRequest发送请求,HttpWebResponse来接收,判断HttpWebResponse中”Content-Ty ...

  2. oracle登陆,在监听服务启动了的情况下,登陆用户还是报错未启动监听服务的错误(刚开始装oracle是能登陆的,重启之后装了plsql)

    刚开始装oracle是能登陆的,重启之后装了140M的plsql,所以有可能是plsql跟oracle监听冲突了,所以我之后换了33M的plsql,oracle就没问题了,可以正常登陆了

  3. springmvc 关于controller的字符编码

    在使用springMVC框架构建web应用,客户端常会请求字符串.整型.json等格式的数据,通常使用@ResponseBody注解使 controller回应相应的数据而不是去渲染某个页面.如果请求 ...

  4. hibernate缓存机制(二级缓存)

    一.why(为什么要用Hibernate缓存?) Hibernate是一个持久层框架,经常访问物理数据库. 为了降低应用程序对物理数据源访问的频次,从而提高应用程序的运行性能. 缓存内的数据是对物理数 ...

  5. Android OpenGL ES(十四)gl10方法解析

    Android 支持 OpenGL 列表 1.GL 2.GL 10 3.GL 10 EXT 4.GL 11 5.GL 11 EXT 6.GL 11 ExtensionPack 我们将使用 GL10 这 ...

  6. POJ 3368/RMQ/线段数

    题目链接 /* 给出一段序列,询问[L,R]区间内最大相同数的个数. 用一个很巧妙地方法,转化成求区间内的最大值的问题. RMQ维护区间最大值. MAX处理: */ for(int i=1;i< ...

  7. NSUserDefault -- synchronize 浅析

    NSUserDefault的使用比较简单:NSUserDefaults *mySettingData = [NSUserDefaults standardUserDefaults];  创建NSUse ...

  8. Windows下将ImageMagick移植到Android平台

    Windows下将ImageMagick移植到Android平台 原文链接  http://www.pedant.cn/2014/06/18/imagemagick-ported-android/ I ...

  9. android 代码动态创建视图

    LinearLayout 如何动态设置 margin? LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(LinearLayou ...

  10. HDU1518:Square(DFS)

    Square Time Limit : 10000/5000ms (Java/Other)   Memory Limit : 65536/32768K (Java/Other) Total Submi ...