第1章:Gradle 基础——构建工具演进、Gradle 优势与核心概念
做 Android 开发这么多年,我见过不少人一上来就敲 Gradle 脚本,却不知道它到底解决了什么问题。今天咱们先聊聊这个“地基”,把来龙去脉理清楚,后面讲缓存和增量编译时你才不会觉得飘。
1. 构建工具的“三代进化”
构建工具说白了就是帮你把源代码变成可运行包的东西。最早那会儿,大家用 Makefile。我入行时维护过一个老项目,Makefile 写了两千行,改个编译参数得翻半天,心里直骂娘。后来 Java 世界流行 Ant,它好歹是 XML 写的,比 Makefile 可读性强点,但 Ant 没有约定,每个项目都得自己写一堆重复逻辑。
再后来 Maven 出现了,它引入了“约定优于配置”。我记忆特别深,第一次用 Maven 时觉得“哇,终于不用自己定义目录结构了”。但它也有硬伤——XML 实在太啰嗦,而且构建周期是固定的,想自定义个任务?折腾半天。
Gradle 算是第三代构建工具。它站在前人的肩膀上,同时吸收了 Ant 的灵活性和 Maven 的约定能力,最关键的是它用 Groovy(或 Kotlin)作为 DSL,写起来像写程序一样自然。
一句话总结进化路线:
- Makefile(纯文本,手动控制)
- Ant(XML,灵活但无约定)
- Maven(XML,约定但死板)
- Gradle(DSL,灵活+约定+高性能)
2. 为什么我选择 Gradle?
说实话,当初从 Maven 迁移到 Gradle 时我也犹豫过。但用了两周后就回不去了。Gradle 有几个杀手锏,特别对我们这种天天和构建打交道的人。
- DSL 表达式力:用 Groovy 或 Kotlin 写构建逻辑,比 XML 直观十倍。举个例子,你想排除某个依赖?一行代码搞定。
- 增量编译:这是本课程的核心之一。Gradle 会记住每个输入和输出,只有改动过的部分才重新执行。我曾经在某个大项目中把单次构建从 8 分钟压到 40 秒,全靠增量。
- 构建缓存:能把一次构建结果复用给其他开发者或 CI。我团队里有个同事每次改一行代码就要全量编译,配置好缓存后他再也不抱怨了。
- 依赖管理:动态版本、冲突解决、传递性依赖控制,比 Maven 更智能。
- 并行执行与守护进程:多任务并行 + 常驻进程,启动速度比 Maven 快一个数量级。
我的习惯:每个新项目我都会先配好构建缓存和增量编译,这就像给项目买个“加速保险”。后面章节会手把手教你配置。
3. 核心概念:Project、Task、Plugin
刚开始接触 Gradle 的人最容易绕晕的就是这三个东西。我用一个比喻帮你理解:
- Project 就是你的“项目”本身。一个 Android App 就是一个 Project,一个 Java Library 也是一个 Project。Gradle 构建时,会为每个模块创建一个 Project 对象。
- Task 是 Gradle 里最小的执行单元。比如编译 Java 源代码是一个 task,打包 APK 是一个 task,运行测试也是一个 task。Task 可以依赖其他 task,形成一张执行图。
- Plugin 说白了就是一堆 task 的集合。你引入 Android 插件,它就自动帮你注册了 assembleDebug、installDebug 等一系列 task。不用自己一个个写。
我记得刚开始带新人时,有个同事问我:“为什么我明明没写 task,却能执行 assemble?” 我告诉他,这就是 Plugin 干的——它把一堆常见的构建步骤封装好了。你只需要关注业务代码,构建的脏活累活交给 Plugin。
曾经踩过的坑:我刚开始自己写自定义 task 时,忘了设置输入输出,结果每次构建都执行 full rebuild,连缓存都救不了。后面讲了增量编译原理后,你就明白为什么必须精确定义 inputs/outputs 了。
下面这张图把三者的关系串起来了:一个 Project 可以配置多个 Plugin,每个 Plugin 注册若干 Task,Task 之间通过依赖形成有向无环图(DAG)。
4. 核心概念速览表
| 概念 | 作用 | 对标 Maven | 实际例子 |
|---|---|---|---|
| Project | 构建单元,代表一个模块或应用 | pom.xml 对应的模块 | settings.gradle 中定义的 app、library |
| Task | 最小执行原子,可配置输入输出 | Maven 的 lifecycle phase(但更灵活) | ./gradlew compileDebugKotlin |
| Plugin | 打包一组 Task 和配置扩展 | Maven 插件 | apply plugin: 'com.android.application' |
5. 再聊几句 Task 的生命周期
Gradle 构建分三个阶段:初始化(读 settings.gradle)、配置(执行所有 build.gradle,生成 Task 图)、执行(按依赖顺序执行 Task)。
你想想看,为啥有些代码写在 doLast 里,有些写在配置区?配置区的代码在“配置阶段”就跑完了,而 doFirst/doLast 里的代码留到“执行阶段”才跑。我之前一个项目里,有人把网络请求写在配置区,结果每次执行 gradle tasks 都能把远程服务器搞挂——这就是没搞清楚阶段。
避坑指南:千万别在配置阶段做耗时操作(比如下载文件、IO 读写)。配置阶段应该只创建 Task 和设置参数,真正的干活留给 doFirst/doLast。
6. 本课程的路线
这 30 章我打算这么安排:先把 Gradle 基础打牢(今天就干了这事),然后重点攻克增量编译原理(第 2-6 章),接着手把手配置构建缓存(第 7-15 章),后面是实战案例分析、问题排查、CI 集成,最后再来点更底层的字节码和输入快照分析。
嗯,今天到这里刚刚好。你脑子里应该有了三个锚点:Project 是你的锅,Plugin 是菜谱,Task 就是一个个烹饪步骤。下节课咱们就深入 Task,看看 Gradle 是怎么判断“这道菜要不要重新炒”的。