作为一名 Android 开发者,世界上最遥远的距离不是生与死,而是我改了一行代码,点击了 "Run",然后看着 Gradle 的进度条在 Building... 处停滞不前。
以前我的项目全量编译一次要 5 分钟,增量编译也要 1-2 分钟。这期间我甚至能去冲杯咖啡、回几个消息,有时候甚至忘了自己刚才为什么要跑代码。上周我终于忍无可忍,花了一天时间对项目的构建系统做了一次“大手术”。
结果非常感人:全量编译降到了 40 秒左右,增量编译更是秒级响应。
今天不谈虚的,直接分享我这次优化的实战过程,希望能帮你省下那些盯着进度条发呆的时间。
第一步:知己知彼(Build Analyzer)
在动手改配置之前,你得先知道慢在哪里。盲目加大内存不一定有用。
Android Studio 自带的 Build Analyzer 是个神器。
- 点击 AS 右侧的
Build标签。 - 编译完成后,点击
Build Analyzer选项卡。
它会直接告诉你哪些 Task 耗时最长,或者是否有插件在拖后腿。我第一次跑的时候,发现竟然有两个老旧的 Gradle 插件在 configuration 阶段就卡了 30 秒。果断移除或升级这些陈旧插件,这是优化的第一刀。
第二步:薅 Gradle 的羊毛(gradle.properties 配置)
这是性价比最高的一步,改几个参数就能见效。打开你项目根目录下的 gradle.properties,检查以下配置:
1. 开启并行编译与守护进程
# 开启 Gradle 守护进程,复用 JVM 实例
org.gradle.daemon=true
# 开启并行编译,利用多核 CPU 优势(这个提升巨大)
org.gradle.parallel=true
# 开启构建缓存,复用之前的构建产物
org.gradle.caching=true
2. 调整 JVM 内存 很多时候慢是因为内存不够,导致 Gradle 频繁 GC。如果你的电脑是 16GB 或 32GB 内存,千万别吝啬。
# 给 Gradle 分配足够的堆内存(根据你电脑配置调整,我是 M2 Pro,给了 4G)
org.gradle.jvmargs=-Xmx4096m -XX:MaxMetaspaceSize=1024m -Dfile.encoding=UTF-8
注意:不要无脑给太大,给太大反而会导致 GC 停顿时间变长。一般 4G-6G 足够应付中大型项目。
第三步:告别 KAPT,拥抱 KSP
这是我这次优化中收益最大的一项。
如果你在用 Room, Glide, 或者 Dagger/Hilt,你大概率在用 kapt。Kapt 的原理是生成 Java 存根(Stubs),这不仅慢,而且容易打断 Gradle 的增量编译链。
Google 推出的 KSP (Kotlin Symbol Processing) 可以直接解析 Kotlin 代码,速度比 Kapt 快 2 倍以上。
迁移步骤很简单:
- 在
libs.versions.toml或build.gradle中引入 KSP 插件。 - 把所有的
kapt关键字替换为ksp。
// 以前
kapt "androidx.room:room-compiler:$room_version"
// 现在
ksp "androidx.room:room-compiler:$room_version"
迁移完这一波,我的编译时间直接砍掉了一分半钟。
第四步:开启 Configuration Cache(配置缓存)
Gradle 的生命周期分为:初始化 -> 配置 -> 执行。 大型项目中,光是“配置”阶段(解析所有 build.gradle 文件)就要花很久。
开启 Configuration Cache 后,Gradle 会缓存配置阶段的结果。第二次构建时,直接跳过配置阶段,直奔主题。
在 gradle.properties 中添加:
org.gradle.configuration-cache=true
排雷预警: 开启这个功能可能会报错,因为某些老旧插件或自定义 Task 可能不兼容(比如在配置阶段读取了系统时间或环境变量)。你需要根据报错信息修一修脚本,但这个折腾绝对值得,它能让你的增量构建瞬间起飞。
第五步:剔除 Debug 包中不必要的资源处理
我们在开发阶段(Debug)其实不需要很多耗时的操作,比如资源压缩、Crashlytics 上传符号表等。
在 app/build.gradle 中做如下优化:
android {
buildTypes {
debug {
// 关闭 Crashlytics 构建 ID 生成(开发时不需要)
ext.enableCrashlytics = false
// 关闭 PNG 压缩(开发时用不到那么小的包)
aaptOptions.cruncherEnabled = false
// 甚至可以配置只编译当前连接设备的架构(比如只打 arm64-v8a)
splits.abi.enable = false
splits.density.enable = false
}
}
}
这能省下很多无意义的 I/O 操作。
总结
做完这一套“组合拳”:
- 基础配置:并行、缓存、大内存。
- 核心替换:KAPT -> KSP。
- 黑科技:Configuration Cache。
- 减负:Debug 模式剔除无用 Task。
我的项目从冷启动 5 分钟变成了 40 秒左右,热启动(改几行代码)通常在 5-8 秒内完成。
这种流畅感,真的会让你爱上写代码(起码不讨厌按 Run 了)。如果你也被 Gradle 折磨,不妨今晚就试试这几招。
P.S. 如果以上都没用,可能你真的需要换一台 M 芯片的 Mac 了……(逃)