启用 Gradle 构建缓存配置

Gradle 构建缓存能够复用上一次构建的输出产物(如编译后的 class 文件、AAR 包、DEX 产物),避免相同输入下重复执行任务。对于大型 Android 项目,配置正确的缓存策略可将增量构建时间降低 50%~80%。本章将涵盖本地缓存、远程缓存、缓存键定制与缓存清理的完整实践。

1. 构建缓存原理与类型

Gradle 使用缓存键(Cache Key)匹配任务输入。当任务的输入(源码、资源、JDK 版本、插件版本、构建脚本等)完全一致时,缓存命中,任务跳过执行直接输出上次结果。

缓存类型 存储位置 共享范围 典型场景
本地缓存~/.gradle/caches/build-cache-1本机所有项目单人开发,切换分支或反复清理项目
远程缓存HTTP 服务器(如 Nginx、S3)团队 / CI 节点CI 机器与开发者共享编译产物
推荐策略:开发环境启用本地缓存 + 远程只读(pull),CI 环境启用远程读写(push)。避免开发机写入不稳定网络导致远程缓存污染。

2. 配置 buildCache(全局 + 项目级)

全局配置文件 ~/.gradle/init.gradle 或 ~/.gradle/init.d/ 下的脚本会对所有项目生效;项目级配置放在 settings.gradle 中。

// settings.gradle 示例
buildCache {
    local {
        enabled = true
        // 缓存路径(可选,默认 ~/.gradle/caches/build-cache-1)
        directory = new File(rootDir, '.build-cache')
        // 缓存保留策略:按大小(MB)或保留天数
        removeUnusedEntriesAfterDays = 30
        // 禁用本地缓存推送远程(开发机)
        push = false
    }
    remote(HttpBuildCache) {
        enabled = true
        url = 'https://cache.example.com/'
        // CI 或授权令牌
        username = System.getenv('CACHE_USER')
        password = System.getenv('CACHE_PASS')
        // 开发机只拉取不推送
        push = System.getenv('CI')?.toBoolean() ?: false
    }
}
注意:远程缓存 url 必须以 / 结尾;若使用自签名 HTTPS,需在 Gradle 启动参数添加 -Dorg.gradle.cache.tls.trustStore。

3. 缓存键策略(Cache Key Customization)

默认缓存键基于任务输入的文件内容哈希(NormalizedPathInputs)+ 任务类型 + 插件版本。当需要忽略某些无关输入(如时间戳、构建机器环境变量)时,可定制缓存键。

// 在 build.gradle.kts 中为特定任务排除无关输入
tasks.withType().configureEach {
    outputs.cacheIf { true }
    inputs.property("gradleVersion", gradle.gradleVersion)
        .withNormalizer(ClassLoaderNormalizer::class.java)
}
// 禁用某个任务的缓存(例如代码生成器每次必须执行)
tasks.named("processResources") {
    outputs.cacheIf { false }
}

常用缓存键调整手段:

  • 文件路径归一化:inputs.file(...).withNormalizer(PathNormalizer)忽略路径差异。
  • 忽略环境变量:在gradle.properties中设置org.gradle.caching=false可全局关闭。
  • 自定义 cacheKey:通过@CacheableTask注解或实现HasCustomActions接口。

4. 清理缓存

缓存堆积可能导致磁盘空间膨胀,或旧缓存包含错误产物。常用清理方法:

# 1. 手动删除整个本地缓存目录
rm -rf ~/.gradle/caches/build-cache-1

# 2. Gradle 内置清理(按保留策略)
./gradlew cleanBuildCache

# 3. 通过 init script 控制保留天数(见 settings.gradle 示例)

# 4. 远程缓存清理:由服务端管理(如配置保留最近 90 天的缓存条目)
实践建议:在 CI 流水线结尾执行 cleanBuildCache 配合 removeUnusedEntriesAfterDays = 7,避免缓存膨胀导致磁盘满;同时在开发机保留 30 天以支持分支切换。

5. 构建缓存工作流程

下图展示了缓存命中与未命中的完整路径:

Gradle 构建缓存工作流程 任务执行请求 计算缓存键 本地缓存命中? 远程缓存命中? 执行任务 输出缓存到本地 复用缓存输出 虚线代表命中路径

6. 常见错误与排查

现象原因解决
本地缓存永远不命中缓存键包含路径或时间戳启用 NormalizedPathInputs 或移除 instantRun/buildId 输入
远程缓存上传失败URL 配置错误或证书问题检查 url 末尾斜杠,添加 -Dorg.gradle.cache.tls.trustStore
缓存占用空间巨大未设置 removeUnusedEntriesAfterDays在 buildCache 块中设置保留策略
Android 资源合并不缓存AGP 部分任务默认不缓存通过 //no-cache 注解或升级 AGP 版本
性能优化点:在多模块项目中使用并行缓存下载(org.gradle.caching.parallel=true),同时限制并发连接数(org.gradle.caching.local.parallelism=4)避免网络拥堵。