如何提高多模块项目的Gradle的编译速度?
Android 项目一旦引入多模块架构,构建速度往往会像踩了刹车一样骤降。很多人第一反应是“Gradle 太慢了”,但实际上大部分项目的编译瓶颈,并非来自 Gradle 本身,而是我们的代码组织与配置方式拖了后腿。
本文将从 Gradle 配置、模块管理、注解处理器和依赖设计四个维度,给出一套可落地的编译优化方案,帮你把浪费在构建上的时间夺回来。
一、基础配置——让 Gradle 火力全开
在写任何业务代码之前,先检查项目的 gradle.properties 是否正确配置。以下是一套推荐的基础优化
简单说明:
-
configuration-cache是 Gradle 的杀手级特性,它能记住整个工程的配置结果,使得配置阶段几乎瞬间完成,尤其对多模块项目效果拔群。如果遇到兼容性问题,可以暂时关闭,但尽量适配它。 -
parallel=true允许独立模块并行编译,多核 CPU 的利用率大幅提升。 -
caching=true配合远程构建缓存,能让 CI 和团队成员之间共享编译结果,下文会细讲。
二、模块级优化——增量编译与按需构建
1. 开启增量编译
在模块的 build.gradle.kts 中,确保 Kotlin 和 Java 的增量编译都已开启:
Kotlin 增量编译依赖于代码的稳定性。如果你的模块经常出现“改了 1 行代码,整个模块重新编译”的情况,往往是以下原因导致增量编译失败:
-
使用
kapt时生成的代码不稳定; -
模块间不合理的
api依赖导致上游变更波及下游; -
常量或内联函数的修改强制重编译。
2. 按需构建,不要一把梭
对于大型项目,并不是每次都需要编译所有模块。你可以通过以下手段按需构建:
- 命令行指定模块:只编译你关心的部分
模块动态包含:某些老旧模块(比如 features:legacy)只在有特定需求时才参与编译
- 单模块独立运行:如果你已经做到了组件化(可独立运行的模块),开发时直接编译运行该组件即可,完全摆脱宿主 App,编译时间降到最低。
三、注解处理器——从 kapt 迁移到 ksp
这是见效最显著的编译优化手段之一。kapt(Kotlin Annotation Processing Tool)会把 Kotlin 代码转为 Java 桩代码再执行注解处理,过程冗长且缓慢。ksp(Kotlin Symbol Processing)则是直接在 Kotlin 语法树上工作,通常能带来 3~5 倍的编译速度提升。
迁移方法:将注解处理器的依赖从 kapt 换为 ksp。
注意:并非所有注解处理器都已经支持 ksp,但主流库(Room、Hilt、Glide 等)正在快速跟进。对于仍需要 kapt 的库,尽量将其范围控制在最小。
四、依赖设计:api vs implementation 的艺术
在多模块项目中,依赖图越深、越宽,编译时波及的范围就越大。正确使用 api 和 implementation 是控制这一影响面的关键:
-
implementation:依赖不会传递给下游模块。上游模块修改时,仅直接依赖它的模块需要重新编译。 -
api:依赖会泄露给下游。上游模块更改任何一个api依赖的接口时,所有传递依赖链上的模块都会触发重编译。
经验法则:
-
除非你确实希望下游模块能直接使用某个第三方库的接口(比如模块对外暴露的类型使用了
Retrofit的类),否则一律用implementation。 -
时常审查模块的依赖列表,避免“为了方便”而滥用
api,这往往会在你不经意间织出一张庞大的重编译网络。
另一个容易被忽视的点是:拆模块不是越细越好。每个 Gradle 模块都有自己的初始化开销(配置、任务图构建)。拆分过细(比如每个页面一个模块)会让配置阶段耗时显著增加。建议以业务边界为基准拆分,一般 10~20 个模块以内是比较健康的状态,超过了就要评估合并的可能性。
五、诊断与排查:找出真正的瓶颈
当你配置完上述优化后编译仍然缓慢,就需要动手诊断了。
- 生成构建扫描报告
-
构建扫描会详细展示各阶段耗时、任务耗时、缓存命中率,帮你精准定位是配置阶段还是任务执行阶段拖慢了整体。
-
检查 Kotlin 增量编译是否生效
在gradle.properties中加入kotlin.incremental.usePreciseJavaTracking=true(Gradle 8.1+ 默认开启),然后观察两次连续编译的耗时差异。如果变化不大,说明增量编译可能因代码结构问题失效。 -
查看依赖树
- 找出重复依赖、冲突依赖和不该出现的传递依赖,及时排除。
六、进阶:远程构建缓存与 Daemon 调优
当团队规模扩大,Remote Build Cache 是质变级优化。它允许 CI 服务器将编译产物上传至共享存储(如 HTTP 缓存节点、Gradle Enterprise),其他开发者拉取代码后直接复用缓存,省去大量本地编译时间。配置方式为在 settings.gradle.kts 中启用:
另外,Gradle Daemon 和 Kotlin Daemon 的内存配置也很关键:
Gradle 版本本身也在不断优化构建性能,Gradle 8.x 的配置缓存稳定性和并行度均远胜 7.x,条件允许的情况下尽量升级。
七、总结
“编译慢”不是 Gradle 的原罪,而是架构与配置失当的并发症。优化顺序应当是:
-
先调好
gradle.properties,让基础设施跑满; -
用 ksp 替代 kapt,消除最大的热点;
-
规范依赖关系,限制重编译半径;
-
必要时诊断构建扫描,精准下刀;
-
最后再用远程缓存等进阶手段锦上添花。
编译速度的提升不是一蹴而就的魔法,而是一次次针对性优化的积累。从今天起,别再忍受无谓的等待,动手还自己一个清爽的构建环境。

