7. Gradle依赖管理:仓库配置、依赖声明、传递与排除、动态版本与快照版本、依赖锁定
依赖管理,说白了就是告诉Gradle:你的代码需要哪些“零件”,从哪里拿,拿哪个版本。我刚开始接触Android时,觉得这不就是加几行代码吗?直到有一次因为依赖冲突,编译花了两个小时,最后发现是某个库偷偷升级了……嗯,从那以后我再也不敢小看依赖管理了。
7.1 仓库配置:你的“零件仓库”
Gradle从哪里下载依赖?答案就是仓库。常见的仓库有这几个:
| 仓库名称 | 说明 | 现状 |
|---|---|---|
| mavenCentral | Sonatype维护的中央仓库 | 推荐首选,稳定可靠 |
| jcenter | JFrog维护的仓库 | 已停止服务,别用了 |
| Google官方仓库 | Android必备,放AndroidX、Material等 | |
| mavenLocal | 本地Maven缓存 | 调试本地库时用 |
我个人习惯在settings.gradle.kts里统一配置仓库,这样所有模块都能共享:
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
google()
mavenCentral()
// 别加jcenter了,它已经凉了
}
}
7.2 依赖声明方式:三种姿势
在Gradle里声明依赖,主要有三种方式。我按使用频率排个序:
- 模块依赖:依赖自己项目里的其他模块
- 外部依赖:从远程仓库下载
- 文件依赖:直接引用本地的jar/aar文件
代码里长这样:
dependencies {
// 模块依赖
implementation(project(":core:network"))
// 外部依赖
implementation("com.squareup.okhttp3:okhttp:4.12.0")
// 文件依赖
implementation(files("libs/some-local-lib.jar"))
}
你想想看,implementation和api有什么区别?简单说:implementation不会把依赖暴露给外部,编译更快;api会传递出去。我建议能用implementation就用它,别偷懒。
7.3 依赖传递与排除:管好“连锁反应”
依赖传递,就是A依赖B,B依赖C,结果你的项目里自动有了C。听起来方便,但坑也在这里。
我曾经遇到一个bug:App里用了两个库,都依赖了不同版本的Gson。结果运行时随机崩溃,查了两天才发现是Gson版本冲突。解决方案就是排除传递依赖:
implementation("com.example:library-a:1.0.0") {
exclude(group = "com.google.code.gson", module = "gson")
}
或者全局排除:
configurations.all {
exclude(group = "com.google.code.gson")
}
./gradlew :app:dependencies命令,可以查看完整的依赖树。我每次遇到依赖问题,第一件事就是跑这个命令。
7.4 动态版本与快照版本:方便但危险
动态版本用+号表示,比如com.example:lib:1.+。意思是“取1.x系列的最新版”。快照版本则是com.example:lib:1.0.0-SNAPSHOT,每次构建都去检查有没有新快照。
说实话,我强烈不建议在生产项目里用动态版本。为什么?因为构建结果不可复现。今天编译好好的,明天可能就挂了。我曾经有个同事用了动态版本,结果CI构建时突然拉到一个有bug的版本,整个团队排查了一下午……
如果你非要用,记得设置缓存时间:
configurations.all {
resolutionStrategy.cacheDynamicVersionsFor(10, "minutes")
resolutionStrategy.cacheChangingModulesFor(0, "seconds")
}
7.5 依赖锁定:给依赖上把锁
依赖锁定,就是把你项目里所有依赖的精确版本记录到一个文件里。这样不管什么时候构建,用的都是同一套版本。
Gradle提供了gradle.lockfile机制。启用方式很简单:
dependencyLocking {
lockAllConfigurations()
}
然后运行:
./gradlew :app:dependencies --write-locks
这会生成一个gradle.lockfile文件。把它提交到Git里,以后构建就会严格按照这个文件来。如果有人改了依赖版本,锁文件会报错,必须手动更新。
知识体系图
这张图把依赖管理的五个核心模块串起来了。从上到下,从左到右,你可以看到:仓库是源头,声明是入口,传递与排除是控制手段,动态版本是双刃剑,依赖锁定是最终保障。
公众号:蓝海资料掘金营,微信deep3321