Gradle 是一个基于 JVM 的自动化构建工具,使用 Groovy DSL 声明配置。现代软件开发包含众多步骤,包括编译、测试、打包等,如果需要手动重复每一过程,将会耗费大量时间、增加出错概率,项目自动化应运而生。在此之前,常见的 Java 构建工具包括 Ant、Gant 和 Maven 等,Gradle 结合了以上工具的优点,基于约定大于配置,通用灵活,是 Android 的官方构建工具。本文将介绍 Gradle 的基本知识、Groovy 基本语法以及 Android 开发中的 Gradle 知识。
入门
搭建环境
确保系统已安装 JDK 1.7及以上,此处将介绍 Gradle 在 Windows 平台下的手动安装。在 https://gradle.org/releases/ 下载最新的 release 包并解压至相应文件夹,然后在系统环境变量添加GRADLE_HOME
,作者的变量值为D:\gradle-5.4.1
,最后再将%GRADLE_HOME%\bin
添加进Path
变量中即可。在命令行中键入gradle -v
验证环境搭建结果。
PS C:\Users\Febers> gradle -v |
Hello World
新建一个工程项目,比如gradle_demo
,然后新建一个build.gradle
文件,在其中输入
task hello { |
在当前文件夹命令行中键入gradle -q hello
即可输出Hello World!
。这里使用的是基于 Groovy 的 DSL(Domain Specific Language,领域特定语言)。
task 和 action 是 Gradle 的重要元素,前者代表一个独立的原子操作,比如复制一个文件、编译一次 Java 代码,这里简单定义一个名为hello
的 task;后者则是前者的组成部分,doLast
代表 task 执行的最后一个 action,task 执行完毕之后会回调该 action。
日志级别
和 Android 类似,Gradle 也定义了日志级别
级别 | 用于 |
---|---|
ERROR | 错误信息 |
QUIET | 重要信息 |
WARNING | 警告信息 |
LIFECYCLE | 进度信息 |
INFO | 信息消息 |
DEBUG | 调试消息 |
上文运行任务所使用到的命令gradle -q hello
中的-q
即为日志的级别开关选项
开关选项 | 输出级别 |
---|---|
无 | LIFECYCLE及以上 |
-q 或 –quiet | QUIET及以上 |
-i 或 –info | INFO及以上 |
-d 或 –debug | DEBUG及以上 |
Project
每个 Gradle 项目都由一个或多个 Project 构成,每个 Project 又都由 Task 构成。一个 build.gradle
文件便是对一个 Project 对象的配置。在 Android 项目中,根目录会存在一个build.gradle
文件,每个模块下也会有一个该文件。
在构建脚本中调用的没有在构建脚本中定义的方法和属性都委派给 Project 对象,比如project.copy()
等价于copy()
、project.buildDir
等价于buildDir
Task
创建任务
task hello { |
输入gradle -q hello*
之后的结果为,说明成功创建任务
Hello World! |
任务顺序
通过dependsOn
指定任务的依赖,通过一个例子理解
task hello { |
输入gradle -q go
之后的输出结果为
hello |
排除任务
在命令行后添加-x go
来排除任务 go,输入gradle hello -x go
之后
> Task :hello |
动态任务
可以通过拓展方法times
动态创建任务
3.times { |
输入gradle -q task0
之后将输出task 0
,已创建的三个任务中的一个
任务属性
标准属性有group
、description
等,除此之外的自定义属性需添加ext
前缀
task hello { |
输出正常
Groovy
Gadle 使用 Groovy 的 DSL 编写,Groovy 是 Apache 推出的 JVM 语言。Groovy 的学习可以参考其官方文档,写得相当友好。Groovy 可以与 Java 无缝连接,甚至可以在其中直接使用 Java 语法,Java 中调用 Groovy 也相当方便。此处只介绍一些与 Java 不同的地方。
Groovy 会默认导入以下包,不需要显示导入
java.io.* |
可以导入 SDK 之后在 IDE 中编写 Groovy 程序,也可以在 build.gradle
中编写代码,在 task
中调用,使用 gradle 命令运行。以下的例子采用后一种方法。
变量与方法
使用 def 关键字来定义变量和方法,可以不指定变量的类型,默认访问修饰符为 public。Groovy 中使用双引号定义字符串的时候类型为GString
而非java.lang.String
,因此可以使用$
输出表达式结果
task t { |
控制台输出
before return |
对象
Groovy 中的类与 Java 类似,不过由于没有访问修饰符,默认为public
,要想实现 Java 默认的包访问权限(default
),可以使用注解@PackageScope
。对于没有可见性修饰的变量,Groovy 会隐式提供setter/getter
方法。以下的两个类是等价的
task t { |
此外 Groovy 使用asType
函数进行类型转换,支持object.with{ }
进行级联操作,支持使用?.
进行非空操作,都是些很眼熟的语法特性
闭包
闭包在 Groovy 中是groovy.lang.Closure
的实例,类似于 Dart 中的函数是 Function 的实例,因此可以像变量一样传递,其语法定义为
//闭包的参数为可选项 |
闭包跟函数不同的地方在于其可以访问外部变量
task t { |
与 Java 中的 Lambda 表达式类似,闭包可以当做参数传递,当闭包为最后一个参数时可写在调用的括号后
文件读取
相较于 Java,Groovy 的文件读写非常简洁友好。在当前文件夹新建一个文件静夜思.txt
task t { |
其他
Groovy 中的流程控制语句(比如if/else
、for/in
、switch/case
)、数据结构(比如List
、Map
)与 Java/Dart 类似,在此便不过多费笔墨,参考官方文档即可。
Gradle Wrapper
Gradle 包装器。为了应对团队开发中 Gradle 环境和版本的差异会对编译结果带来的不确定性,使用 Gradle Wrapper,它是一个脚本,可以指定构建版本、快速运行项目,从而达到标准化、提到开发效率。Android Studio 新建项目时自带 Gradle Wrapper,因此 Android 开发者很少单独下载安装 Gradle
Gradle Wrapper 的工作流程如下图
使用 Gradle Wrapper 启动 Gradle 之后,如果指定版本的 Gradle 没有被下载关联,会先从官方仓库下载到用户本地,进行解包并执行批处理文件。后续的构建运行都会重用这个解包的运行时安装程序
构建 Gradle Wrapper
Gradle 内置 Wrapper Task,执行 Wrapper Task 就可以在项目目录中生成对应的目录文件。在项目根目录执行gradle wrapper
命令即可。之后根目录的文件结构如下
├── gradle |
文件含义为
- gradle-wrapper.jar :包含 Gradle 运行时的逻辑代码。
- gradle-wrapper.properties :负责配置包装器运行时行为的属性文件
- gradlew:Linux 平台下,用于执行 Gralde 命令的包装器脚本。
- gradlew.bat:Windows 平台下,用于执行 Gradle 命令的包装器脚本。
查看.properties
文件
distributionBase=GRADLE_USER_HOME |
属性含义为
- distributionBase:Gradle 解包后存储的主目录。
- distributionPath:distributionBase 指定目录的子目录。distributionBase+distributionPath 为 Gradle 解包后的存放位置。
- distributionUrl:Gradle 发行版压缩包的下载地址。
- zipStoreBase:Gradle 压缩包存储主目录。
- zipStorePath:zipStoreBase 指定目录的子目录。zipStoreBase+zipStorePath 为 Gradle 压缩包的存放位置。
如果官方包发行版下载缓慢,可以手动更改distributionUrl
为可用地址
使用 Gradle Wrapper
使用gradlew.bar
代替gradle
运行 Gradle Project,首次使用会下载 Gradle 到配置文件指定的位置,作者的路径为C:\Users\23033\.gradle\wrapper\dists\gradle-5.4.1-bin\e75iq110yv9r9wt1a6619x2xm\gradle-5.4.1
PS D:\Work\Gradle\gradle_demo> .\gradlew.bat t |
再次使用该命令便不会重复下载。升级 Gradle 版本可以通过gradlew wrapper –gradle-version 5.*.*
命令实现
Gradle 插件
Gradle 中的插件可分为两类
- 脚本插件:额外的构建脚本,类似于一个 build.gradle
- 对象插件:又叫二进制插件,是实现了 Plugin 接口的类
应用插件又分为两个步骤,一是解析插件,二是通过apply()
把插件应用到项目中。
脚本插件
在根目录新建一个other.gradle
文件,内容如下
ext { |
将build.gradle
内容修改为
apply from: 'other.gradle' |
输出结果
PS D:\Work\Gradle\gradle_demo> .\gradlew.bat t |
对象插件
对象插件是实现了org.gradle.api.plugin
接口的插件,又可分为内部插件和第三方插件
内部插件
使用以下方法应用 Java 插件(因为默认导入org.gradle.api.plugin
包,所以可以去掉包名)
apply plugin: org.gradle.api.plugins.JavaPlugin |
第三方插件
一般为 jar 文件,通过buildscript
配置,此处引入 Android Gradle 插件
buildscript { |
如果第三方插件被托管到 Gradle - Plugins,也可以不使用buildscript
plugins { |
自定义对象插件
Plugin 接口中定义了一个apply
方法,重写该方法,在其中通过传进来的参数Object o
(实际为 Project 类型)调用 task 新建一个任务
class MyPlugin implements Plugin { |
输入命令gradle myTask
即可验证
Android 中的 Gradle
为了支持 Android 项目的构建,Google 为 Gradle 编写了 Android 插件,组成 Android 构建系统。Android Studio+Gradle 是目前最流行的 Android 开发构建环境。关于 Android 构建配置可查阅官方文档 配置构建
模块类型
Android Studio 中的每个项目包含一个或多个含有源代码文件和资源文件的模块,这些模块可以独立构建测试,模块类型包含以下几种
- Android 应用程序模块:可能依赖于库模块,构建系统会将其生成一个 apk 文件
- Android 库模块:包含可重用的特定于 Android 的代码和资源,构建系统将其生成一个 aar 文件
- App 引擎模块:包含应用程序引擎继承的代码和资源
- Java 库模块:包含可重用的代码,构建系统将其生成一个 jar 文件
项目结构
在 Android Studio 中,Android 项目视图如下,以开发者个人项目 UESTC_BBS 为例
所有构建稳健位于 Gradle Scripts 层级下,文件作用如下
- 项目 build.gradle:配置项目整体属性,比如指定的代码仓库、依赖的 Gradle 版本等
- 模块 build.gradle:配置当前模块的编译参数
- gradle-wrapper-properties:配置 Gradle Wrapper
- gradle-properties:配置 Gradle
- setting.gradle:配置 Gradle 的多项目管理
- local.properties:存放 Android 项目的私有属性配置,如 SDK 路径
- multiDexKeep.pro、proguard-rules.pro:可选的混淆文件,用于配置放置在主 Dex 的类、声明避免混淆的类
项目 build.gradle
典型的项目build.gradle
文件如下
buildscript { |
其中google()
是配置 Google 的 Maven 仓库,maven { url "https://maven.google.com" }
同理
模块 build.gradle
典型的模块build.gradle
文件如下
apply plugin: 'com.android.application' |
第一行 apply 的是一个application
,说明当前模块为一个应用程序模块,Gradle 的 Android 插件分为以下几种
- 应用程序插件:插件 id 为
com.android.application
,构建生成 apk - 库插件:插件 id 为
com.android.library
,构建生成 aar - 测试插件:插件 id 为
com.android.test
,用于测试其他模块 - feature 插件:插件 id 为
com.android.feature
,用于创建 Android Instant App - instant App 插件:插件 id 为
com.android.instantapp
,是 Android Instant App 的入口
很多属性都可以望文生义,此处不再赘述。
参考