Android - 解决 Gradle 循环依赖问题

随着项目越来越大,使用的第三方库也越来越多,难免有时候会库之间的依赖冲突问题,如何解决呢?

查看依赖关系

很简单,在项目根目录执行下面的命令。

1
./gradlew :app:dependencies --configuration compile
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
Incremental java compilation is an incubating feature.
:app:dependencies
------------------------------------------------------------†
Project :app
------------------------------------------------------------
compile - Classpath for compiling the main sources.
+--- com.android.support:appcompat-v7:25.2.0
| +--- com.android.support:support-annotations:25.2.0
| +--- com.android.support:support-v4:25.2.0
| | +--- com.android.support:support-compat:25.2.0
| | | \--- com.android.support:support-annotations:25.2.0
| | +--- com.android.support:support-media-compat:25.2.0
| | | +--- com.android.support:support-annotations:25.2.0
| | | \--- com.android.support:support-compat:25.2.0 (*)
| | +--- com.android.support:support-core-utils:25.2.0
| | | +--- com.android.support:support-annotations:25.2.0
| | | \--- com.android.support:support-compat:25.2.0 (*)
| | +--- com.android.support:support-core-ui:25.2.0
| | | +--- com.android.support:support-annotations:25.2.0
| | | \--- com.android.support:support-compat:25.2.0 (*)
| | \--- com.android.support:support-fragment:25.2.0
| | +--- com.android.support:support-compat:25.2.0 (*)
| | +--- com.android.support:support-media-compat:25.2.0 (*)
| | +--- com.android.support:support-core-ui:25.2.0 (*)
| | \--- com.android.support:support-core-utils:25.2.0 (*)
| +--- com.android.support:support-vector-drawable:25.2.0
| | +--- com.android.support:support-annotations:25.2.0
| | \--- com.android.support:support-compat:25.2.0 (*)
| \--- com.android.support:animated-vector-drawable:25.2.0
| \--- com.android.support:support-vector-drawable:25.2.0 (*)
+--- com.android.support:preference-v7:25.2.0
| +--- com.android.support:support-v4:25.2.0 (*)
| +--- com.android.support:appcompat-v7:25.2.0 (*)
| \--- com.android.support:recyclerview-v7:25.2.0
| +--- com.android.support:support-annotations:25.2.0
| +--- com.android.support:support-compat:25.2.0 (*)
| \--- com.android.support:support-core-ui:25.2.0 (*)
+--- com.android.support:recyclerview-v7:25.2.0 (*)
+--- io.reactivex:rxandroid:1.2.1
| \--- io.reactivex:rxjava:1.1.6
+--- com.squareup.okhttp3:logging-interceptor:3.3.1
| \--- com.squareup.okhttp3:okhttp:3.3.1
| \--- com.squareup.okio:okio:1.8.0
+--- com.squareup.retrofit2:retrofit:2.1.0
| \--- com.squareup.okhttp3:okhttp:3.3.0 -> 3.3.1 (*)
+--- com.squareup.retrofit2:adapter-rxjava:2.1.0
| +--- com.squareup.retrofit2:retrofit:2.1.0 (*)
| \--- io.reactivex:rxjava:1.1.5 -> 1.1.6
+--- com.squareup.retrofit2:converter-gson:2.1.0
| +--- com.squareup.retrofit2:retrofit:2.1.0 (*)
| \--- com.google.code.gson:gson:2.7
+--- com.squareup.retrofit2:converter-scalars:2.1.0
| \--- com.squareup.retrofit2:retrofit:2.1.0 (*)
+--- com.squareup:otto:1.3.8
\--- com.umeng.analytics:analytics:latest.integration -> 6.0.9
(*) - dependencies omitted (listed previously)
BUILD SUCCESSFUL
Total time: 0.851 secs
  • 版本:唯一的依赖。
  • 版本(*):还存在该库其他版本的依赖或者间接依赖,并且默认选择()所标注的版本。
  • 版本1->版本2(*):还存在该库其他版本的依赖或者间接依赖,并且选择 版本2。

排除版本冲突

1
2
3
4
5
+--- io.reactivex:rxandroid:1.2.1
| \--- io.reactivex:rxjava:1.1.6
+--- com.squareup.retrofit2:adapter-rxjava:2.1.0
| +--- com.squareup.retrofit2:retrofit:2.1.0 (*)
| \--- io.reactivex:rxjava:1.1.5 -> 1.1.6

你可以看到 io.reactivex:rxjava 这个项目其实是有依赖冲突的,但是 gradle 很强大自动帮我们解决了,但是开发中往往经常 gradle 自动解决的依赖关系会出错。

这里我们可以把 com.squareup.retrofit2:adapter-rxjava 中的 rxjava:1.1.5 直接排除掉。

我们使用 exclude 来指定排除项。

1
2
3
compile ('com.squareup.retrofit2:adapter-rxjava:2.1.0') {
exclude module: 'rxjava'
}

再次执行

1
./gradlew :app:dependencies --configuration compile

就变成了

1
2
3
4
+--- io.reactivex:rxandroid:1.2.1
| \--- io.reactivex:rxjava:1.1.6
+--- com.squareup.retrofit2:adapter-rxjava:2.1.0
| +--- com.squareup.retrofit2:retrofit:2.1.0 (*)

举一反三

exclude 的语法其实很简单

我们知道依赖的完整语法还以是这样的:

1
compile group: 'foo', name: 'foo', version: '0.1'

一般简写成:

1
compile 'foo:foo:0.1'

那么 exclude 完整版:

1
2
3
compile (group: 'foo', name: 'foo', version: '0.1') {
exclude group:'groupName' module:'modelName'
}

如果单独指定 group,就是把这个 group 的都排除掉。

更多

Gavin Liu wechat
欢迎您扫一扫上面的二维码,订阅我的微信公众号!