本文转载自原文链接
A: compile ‘com.test.aaa’
B : compile 'com.test.bbb'
C: compile 'com.test.ccc'
D: compile 'com.squarequ.okhttp3'
例如 自己的项目中依赖了 okhttp 还依赖了A B C 三个第三方包,A B C 中都依赖了 okhttp ,直接编译 不能通过 报错
Error:Error converting bytecode to dex:
Cause: com.android.dex.DexException: Multiple dex files define Lokhttp3/Address;
compile ('com.test.aaa'){
exclude group'com.squarequ.okhttp3'
}
这样就去掉了A 依赖中的okhttp . B C 同理。
什么是传递依赖
在Maven仓库中,构件通过POM(一种XML文件)来描述相关信息以及传递性依赖。Gradle 可以通过分析该文件获取获取所以依赖以及依赖的依赖和依赖的依赖的依赖,为了更加直观的表述,可以通过下面的输出结果了解。
+--- org.springframework:spring-web:4.3.4.RELEASE
| | +--- org.springframework:spring-aop:4.3.4.RELEASE
| | +--- org.springframework:spring-beans:4.3.4.RELEASE
| | +--- org.springframework:spring-context:4.3.4.RELEASE
| | \--- org.springframework:spring-core:4.3.4.RELEASE
- 1
- 2
- 3
- 4
- 5
可以看到,我们的项目依赖了spring-web
,然而spirng-web
却依赖了一众spring的全家桶,借助Gradle的传递性依赖特性,你无需再你的脚本中把这些依赖都声明一遍,你只需要简单的一行,Gradle便会帮你将传递性依赖一起下载下来。
compile `org.springframework:spring-web:4.3.4.RELEASE`
- 1
传递依赖特性可以轻松地通过transitive参数进行开启或关闭,上面的示例中如果要忽略spring-web
的传递性依赖可以采用指定transitive = false
的方式来关闭依赖传递特性,也可以采用添加@jar
的方式忽略该依赖的所有传递性依赖。
compile("org.springframework:spring-web:4.3.4.RELEASE") {
transitive = false
}
- 3
compile `org.springframework:spring-web:4.3.4.RELEASE@jar`
- 下面的语句,可以全局性的关闭依赖传递特性。
configurations.all { transitive = false }
- 3
排除依赖
有些时候你可能需要排除一些传递性依赖中的某个模块,此时便不能靠单纯的关闭依赖传递特性来解决了。这时
exclude
就该登场了,如果说@jar
彻底的解决了传递问题,那么exclude
则是部分解决了传递问题。然而实际上exclude
肯能还会用的频率更更频繁一些,比如下面几种情况。- 依赖冲突时,如果有两个依赖引用了相同jar包的不同版本时,默认情况下gradle会采用最新版本的jar包,此时可以通过排除选项来排除。
- 运行期无需此模块的。
- 无法正常获取到此传递依赖,远程仓库都不存在的。
- 版权原因需要排除的。
- 其他原因。
可以通过configuration配置或者在依赖声明时添加
exclude
的方式来排除指定的引用。exclude可以接收group和module两个参数,这两个参数可以单独使用也可以搭配使用,其中module可以理解为对应GAV中的artifactId,也就是
compile group: 'org.gradle.test.classifiers',name: 'service',version: '1.0'
中的中间name部分。configurations { //编译期排除commons模块 compile.exclude module: 'commons' //在整个构建过程中排除pkaq.tiger:share all*.exclude group: 'pkaq.tiger',module: 'share' } dependencies { compile("pkaq.tiger:web:1.0") { exclude module: 'share' } }
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
使用强制版本
当然,有时候你可能仅仅是需要强制使用某个统一的依赖版本,而不是排除他们,那么此时
force
就该登场了。指定force = true
属性可以冲突时优先使用该版本进行解决。compile('org.hibernate:hibernate:3.1') { force = true }
- 3
全局配置强制使用某个版本的依赖来解决依赖冲突中出现的依赖
configurations.all { resolutionStrategy { force 'org.hamcrest:hamcrest-core:1.3' } }
- 5
使用动态版本
如果你想让你的工程始终采用最新依赖,那么Gradle提供了一种方式可以始终保证采用依赖的最新版本而无需每次手工检查修改版本。
使用加号+
,可以让Gradle在每次执行构建时检查远程仓库是否存在该依赖的新版本,如果存在新版本则下载选用最新版本。当然也可以指定依赖某个大版本下的最新子版本,1.+
表示始终采用该依赖最新的1.x
版本的最新依赖。compile 'org.springframework:spring-web:+'
- 1
虽然这是看上去十分风骚的一种用法,但这无疑会降低你系统构建的速度同时提高构建失败的风险。因为Gradle不得不每次检查远程仓库是否存在最新版本,同时新版本也可能带来无法预知的兼容性问题,比如
quartz2.x
较之于quartz1.x
,common-lang3
较之于common-lang
等。一个综合示例
compile('org.hibernate:hibernate:3.1') { // 冲突时优先使用该版本 force = true // 依据构建名称排除 exclude module: 'cglib' // 依据组织名称排除 exclude group: 'org.jmock' // 依据组织名称+构件名称排除 exclude group: 'org.unwanted',module: 'iAmBuggy' // 为本依赖关闭依赖传递特性 transitive = false }