定义
Gradle是一个基于Apache Ant和Apache Maven概念的项目自动化构建开源工具,它使用一种基于Groovy的特定领域语言(DSL)来声明项目设置, 项目配置简单且任务扩展方便。
构建工具的前世今生
Gradle 诞生前有两个非常流行的自动化构建工具Ant和Maven,下列表格对比这两个构建工具的优缺点:
Gradle是基于Ant和Maven诞生的自动化构建工具,那么它必须要同时拥有Ant和Maven的优势,也就是说Gradle具有如下特点:
- 包含依赖管理器,方便引用外部依赖库
- 具有默认的构建任务周期
- 灵活的自定义构建逻辑
Gradle基础
本节重点介绍下Gradle的基础内容,包括运行机制和脚本内容的分析。
Gradle工作流程
Gradle 工作流程分为三个阶段,如下图所示:
- initialization
Gradle初始化阶段会到root工程根目录找到setting.gradle文件,所有在该文件中声明的工程均是Gradle自动化构建的工程 - configure
Gradle初始化过后就会根据setting.gradle中配置的所有工程目录下找build.gradle文件,然后分析build.gradle文件,确定需要执行的任务以及任务的顺序 - build 根据configure阶段确定的Task执行顺序执行Task任务
脚本分析
Gradle有很多插件,这里主要分析Android插件的脚本配置。
setting.gradle
Setting.gradle中主要是声明了哪些Gradle自动化构建的工程,内容如下所示:
include ':app', ':library1', ':library2’
上面内容是包括三个Gradle工程,其中冒号可以理解为/,解释为构建工程的相对目录
根目录build.gradle
根目录build.gradle是对所有Gralde工程均起作用的全局声明,内容如下:
- buildscript 该标签是编译脚本的作用域,也就是对Gradle的配置,其中repositories是Gradle构建脚本的仓库声明,其中dependencies也是Gradle构建脚本所需要的,这里明显是Android工程的Gradle构建工具
- repositories 仓库的意思,就是声明依赖库的地址,allprojects声明的是所有Gradle工程中引用外部库的地址,当有一些lib库放在私有仓库里,需要在这里面添加私有仓库;其中buildscript中的声明的是Gradle构建工具需要依赖的仓库
- task 这里默认声明了一个task,这个Task是用于删除Gradle构建过程生成的文件,Task用法后面再具体说
Android工程build.gradle
Android 工程中的build.gradle文件内容重点是android标签里面的特殊配置项,这里贴一个简单的配置:
-
apply plugin
表示当前Gradle工程构建过程需要使用到的插件,其中com.android.application表示的是使用Android项目的构建过程,当然也可以引用其它插件,前提是在root project的build.gradle中的buildscipt中的dependencises中配置,这里由于配置了com.android.tools.build:gradle所以可以直接使用Android插件 -
android
这个是Android工程特有的配置项,这里介绍一下几个基本配置选项:compileSdkVersion: 编译时使用的SDK版本
buildToolsVersion: 编译时使用的编译工具的版本
applicationId: 应用唯一标识
buildTypes: 编译类型,一般默认deubg和release两种,可以自定义Android里面有很多配置选项,基本就能满足日常开发需求
-
dependencies
依赖标签,主要是设置工程需要的外部库,里面有很多依赖方式,这个具体后面介绍
依赖
依赖主要是引用外部库的过程,这里需要说明两点:仓库以及依赖方式
- 仓库
Gradle中仓库声明主要使用repositories,除了使用远程仓库,还可以使用本地仓库,如在工程中依赖aar时,就是使用的本地仓库:
repositories {
flatDir {
dirs 'libs' // aar目录
}
}
这里是把本地libs目录当作仓库使用
- 依赖
依赖方式比较多,Gradle3.0后又对依赖方式进行了修改,这里列出不同版本以及不同依赖方式之间的差别: 需要注意如下几点:
- implementation和api主要差别是可见性,api的可见性更强
- 上面的依赖方式往往结合Flavor使用构建不同的Variant
依赖远程库文件主要由三部分构成:
group Name version
如下所示:
Name:appcompat-v7
Version:25.1.0
Variant
Android 主要使用BuildType和Product Flavor构建多种Variant
-
BuildType
BuildType构建类型其实很有用,比如配置签名,测试链接,以及混淆等,对日常测试开发很有帮助,如下就定义了在不同的构建类型里面定义了不同的访问连接:
BuildType默认有debug和release两种: -
Product Flavor
Product Flavor表示不同特点的产品,例如APK打包发布时需要发不到不同的应用市场,开发者需要设置不同渠道的渠道号,有的时候还需要针对不同渠道的产品定制特殊的图标或者界面。- 设置不同Product Flavor: 上图设置了不同的ProductFlavor,内容是不同渠道的渠道号,这样在构建不同的产品时,渠道号就直接被修改了
- 生成不同的Product 源集 定制特定的功能,可以将功能独立出来,然后根据不同的Product实现,生成不同的Product源集需要了解下列规则:
- java文件:java文件需要在product具体包名下生成,不可在main中也生成,否则会出现类被定义2次的错误
- drawable和layout文件:会直接覆盖main源集中相同名称的资源
- value目录文件:合并内容
- 构建Variant
上述步骤是配置不同的Variant,当配置完成后,就可以执行编译命令,一般编译的时候,会使用如下命令构建:
./gradlew assemble
该命令会构建所有的的Variant,且产物的数量为BuildTypes x Product Flavor, 如果想要只构建某一个或者一类的Variant,可以执行如下构建命令:
./gradlew assemble + Product Name(可选) + BuildTypes(可选)
Task
Task是Gradle中一个非常重要的工具,通过使用Task能完成一些特定的需求,本节主要从以下三个方面说明:
- Task使用
- Task解析
- Hook Task
Task使用
声明Task有好几种方式,下面展示一种直接定义的方式:
直接执行gradle命令运行:这里注意输出:
Configure project:app
Hello world
其中在Hello Task中定义的内容在Configure阶段就输出了,这里再看下Gradle执行流程:
如果想要在build task阶段执行Task,可以将task定义如下:
任务执行结果如下: 可以看出这里任务是在Task执行阶段运行,这里的<<符号代表doLast的意思,具体后面说明Task解析
上面简单说明了Task的使用,这里主要解析一下Task。
Task内部定义了很多属性和动作,本质上是一个定义了很多方法和属性的接口,所有的方法都已经被DefaultTask实现了,所以在Gradle中使用Task都是基于DefalutTask来实现的。
每个Task中都包含了一个Action对象的集合,这个动作都会被按照顺序执行,动作为doLast和doFirst方法,这里举一个简单的例子:
- 没有在闭包doLast和doFirst中定义的将会在Gradle的Configure阶段执行
- 闭包doLast和doFirst在Gradle中的Build Task阶段执行
- doLast和doFirst同种声明从上往下优先级递增
总结:
Task归根结底是一个类,所以也可以继承task来完成一些特定动作,这里不做自定义task的介绍,比较少用到,这里主要介绍几个常用的特定task,如copy,zip,delete,下面例举删除的task的使用:
HooK Task
Hook Task是指在项目构建的过程中插入自定义任务,完成一些特定的需求,Hook的点有很多,主要能Hook两个阶段:
Configure阶段和Build阶段进行Hook,这里简单举两个例子,后面会在进阶篇重点讲解-
Hook Configure阶段
上面是在构建Task有向图的时候忽略一些Task,这里直接忽略AndroidTest任务 -
Hook Build阶段
这里是对编译的产物进行处理
总结
本篇主要从整体上介绍一下Gradle,重点要理解Gradle的执行流程,以及build.gradle文件中的配置作用已经作用范围,下一篇将重点介绍Gradle在Android中比较高级的用法。