4. Gradle 构建缓存(Build Cache)与依赖缓存的区别:构建缓存 vs 依赖缓存、本地缓存 vs 远程缓存、启用远程构建缓存配置模板
在 AGP 升级过程中,许多开发者混淆了 Gradle 的构建缓存(Build Cache)和依赖缓存(Dependency Cache)。两者虽然都利用“缓存”提升构建速度,但存储内容、触发条件和生命周期截然不同。本章从原理、对比、本地/远程拓扑、配置模板四个层面厘清差异,并给出可直接落地的远程构建缓存配置。
4.1 构建缓存 vs 依赖缓存 —— 核心区别
| 维度 | 构建缓存(Build Cache) | 依赖缓存(Dependency Cache) |
|---|---|---|
| 缓存对象 | Task 输出产物(.class、.dex、APK、AAR 中间产物等) | 远程仓库下载的依赖文件(JAR、AAR、POM 等) |
| 触发条件 | Task 输入(源码、资源、配置)未变 | 依赖声明(GAV 坐标)未变 |
| 存储位置 | ~/.gradle/caches/build-cache-*(本地)或远程 HTTP 服务器 | ~/.gradle/caches/modules-2(固定路径) |
| 生命周期 | 由 Gradle 自身管理,按 LRU 淘汰,可手动清理 | 除非用户手动删除或 Gradle 版本升级,几乎永久保留 |
| 跨项目共享 | 通过远程构建缓存共享,无需重复构建 | 只能本地副本共享,同一台机器不同项目共用 modules-2 |
| AGP 版本影响 | Task 实现变更(如 AGP 8.x → 9.x)可能导致缓存失效 | 依赖坐标不变即命中,与 AGP 版本无关 |
| 性能贡献 | 跳过 Task 执行(编译、打包、签名等) | 跳过网络下载和解压(已缓存直接解压) |
实战注意:AGP 升级后经常遇到“构建缓存未命中”问题,这是因为 Task 的缓存键(cache key)包含了 Gradle 插件版本、AGP 版本、构建工具版本等输入。此时应优先检查构建缓存,而不是怀疑依赖缓存 —— 依赖缓存通常不受版本变更影响。
4.2 本地缓存 vs 远程缓存
无论构建缓存还是依赖缓存,都可以分为本地和远程两层。下表总结各层的用途和风险。
| 缓存层级 | 构建缓存 | 依赖缓存 |
|---|---|---|
| 本地缓存 | ~/.gradle/caches/build-cache-1,自动启用 | ~/.gradle/caches/modules-2,自动启用 |
| 远程缓存 | 需要显式配置 RemoteBuildCache(HTTP/HTTPS) | 依赖仓库本身即是远程缓存(Maven Central、Google Maven 等) |
| 数据一致性 | 远程构建缓存存储 Task 产物,需保证构建环境一致 | 远程仓库依赖由发布者保证一致性 |
| 网络要求 | 需要可靠的局域网或云端缓存服务器 | 必须可访问外部依赖仓库 |
| 常见问题 | 缓存键污染、过期缓存未清理 | 仓库不可用、依赖被篡改(校验失败) |
4.3 启用远程构建缓存 —— 配置模板
Gradle 远程构建缓存允许将 Task 输出推送到共享的 HTTP 服务器(如 Gradle Build Cache Node 或自定义缓存后端),供团队所有机器命中。以下配置放置在项目根目录的 gradle.properties 或 settings.gradle.kts/settings.gradle 中。
配置要点:
- 远程缓存服务器必须支持 PUT/GET 且返回合理响应码(200/304)。
- 建议同时启用本地缓存作为第一级缓存,避免频繁存取远程。
- 生产环境务必开启 HTTPS 并配置鉴权。
Kotlin DSL — settings.gradle.kts
// 在 settings.gradle.kts 中配置远程构建缓存
buildCache {
local {
isEnabled = true // 启用本地构建缓存
directory = File(rootDir, ".gradle/build-cache")
removeUnusedEntriesAfterDays = 7 // 7天未使用自动清理
}
remote {
url = uri("https://cache.company.com:8080/cache/")
isEnabled = true
isPush = true // 允许本机将缓存推送到远程
// 可选鉴权配置
credentials {
username = "build-cache-user"
password = System.getenv("GRADLE_CACHE_PASSWORD") ?: ""
}
}
}
Groovy DSL — settings.gradle
// settings.gradle
buildCache {
local {
enabled = true
directory = "${rootDir}/.gradle/build-cache"
removeUnusedEntriesAfterDays = 7
}
remote(HttpBuildCache) {
url = 'https://cache.company.com:8080/cache/'
enabled = true
push = true
credentials {
username = 'build-cache-user'
password = System.getenv('GRADLE_CACHE_PASSWORD') ?: ''
}
}
}
常见错误:
- 忘记在
settings.gradle中配置远程缓存,而只在build.gradle中引用 — 构建设置必须放在 settings 层。 - 远程缓存服务器不可达时,构建会降级为仅本地缓存,但不会报错中断,导致团队误以为命中远程。
- 同一项目在不同机器使用不同的 JDK 或 AGP 版本会导致缓存键不同,远程命中率为 0 — 应统一开发环境。
4.4 整体缓存拓扑关系图
下图展示了构建缓存与依赖缓存在一次构建中的位置和交互流程,以及本地/远程各层如何协作。
4.5 调试与验证缓存策略
启用远程构建缓存后,通过以下方式验证是否生效:
- 构建日志:添加
--info查看Task cache store来源。命中远程时会显示Remote,本地命中显示Local。 - 清理实验:
./gradlew clean后第二次构建,若 Task 输出全部FROM-CACHE则缓存工作正常。 - 远程监控:检查缓存服务器的 PUT/GET 请求日志,确认本机是否有推拉动作。
性能建议:若团队使用 CI/CD,建议 CI 节点同时开启
push = true,开发者节点设为push = false(只读远程),避免多人同时写入导致缓存碎片。