Android Studio 默认的构建工具为 Gradle。在使用 Gradle 的过程中会碰到一些概念,理清他们的含义关系对我们使用和深入理解 Gradle 至关重要。
Gradle 是基于 JVM 的构建工具。他本身使用 jave 写的,gradle 的脚本也就是 build.gradle 通常是用 groovy 语言。
Android SDK Build-Tools 是构建 Android apk、AAR 文件等 Android 平台产物所需的一个 Android SDK 组件,安装在 <sdk>/build-tools/
目录下。
//build-tools/
├── ⋮
├── aapt2
├── d8
├── apksigner
├── zipalign
├── ⋮
zipalign
进行优化是基于 Gradle 的插件,Android Gradle 主要就是调用[Android BuildTools]这个包里的工具实现编译打包 Apk 等功能。
注:AGP3.0.0 或更高版本,插件会使用默认版本的 build Tools 无需指定。
android { buildToolsVersion "33.0.1"}
项目的根目录的 gradle/wrapper 下
/gradle/wrapper/
├── gradle-wrapper.jar
└── gradle-wrapper.properties
负责下载管理特定版本的 gradle,确保不同环境中项目运行在相同个 gradle 版本里,还能达到复用效果。
gradle-user-home
├── caches // modules-2和jars-3缓存依赖和产物,且各个版本各个项目中共用
│ ├── jars-3
| ├── transforms-3
│ └── modules-2
├── wrapper //存放不同版本的gradle
│ └── dists
│ ├── ⋮
│ └── gradle-7.4-bin
| └── xxxxxxxx
| └──gradle-7.3.3 //其实这是gradle home路径
└── gradle.properties
默认在位置位于
gradle-home
├── bin
│ ├── gradle.bat
│ └── gradle
├── init.d
│ ├──..
│ └── xx.gradle
└── lib
├──...
├── gradle-wrapper-7.3.3.jar
├── gradle-tooling-api-7.3.3.jar
├──...
└── plugins
├── ...
├── gradle-publish-7.3.3.jar
├── commons-codec-1.15.jar
└──...
其实就是 gradle 的安装目录,里面主要包括 Gradle 的可执行文件、库文件、插件等,gradle 执行时会自动加载使用安装目录内的文件插件。
Gradle 执行构建是有生命周期的,分三个阶段初始化阶段(Initialization Phases),配置阶段(Configuration Phases)和执行阶段(Execution Phases)。
*注意:*执行任何 task 都会走初始化阶段和配置阶段
执行上一个阶段也就是配置阶段构造好的有向无环图任务。
tasks.register('test') {
println '该语句会在配置阶段执行'
doLast {
println '该语句会在执行阶段运行'
}
}
初始化阶段主要有两个能接收回调的地方 settingEvaluated{}和 gradle.projectsLoaded {}
//settings.gradle配置执行完成
gradle.settingsEvaluated {
...
}
settingEvaluated{}setting 创建加载成功。在此之前有几项 gradle 有几项重要的工作已经完成。
// 所有 Project 对象创建(注意:此时 build.gradle 中的配置代码还未执行)
gradle.projectsLoaded {
...
}
初始化阶段还有扫描项目下的所有包含位于根 project 和子 project 中的 build.gradle 并对应生成 Project 对象,对象创建完成之后就会调用 gradle.projectsLoaded{},但注意此时 build.gradle 中的配置代码还未执行。
配置阶段会对项目下的每个 build.gradle 进行配置,如上图,beforeProject{}/project.beforeEvaluated{}和 afterProject{}/after.beforeEvaluate 会执行多次,这取决于构建项目下有几个 project。
每个 task 执行前后,我们也有方式去监听:主要是使用 gradle.taskGraph.beforeTask{} 和 gradle.taskGraph.afterTask {},如下:
gradle.taskGraph.beforeTask { Task task ->
println "executing $task ..."
}
gradle.taskGraph.afterTask { Task task, TaskState state ->
if (state.failure) {
println "FAILED"
}
else {
println "done"
}
}
root-project
├── buildSrc
| ├── ...
│ └── build.gradle
├── sub-project
│ └── build.gradle
├── build.gradle
├── settings.gradle
├── gradle.properties
├── gradle
│ └── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew(Unix Shell script)
└── gradlew.bat(Windows batch file)
//gradle.properties中
mVersionName=1.12.1
//build.gradle
println("mVersion name in gradle.properties ${mVersionName}")
Gradle 世界里经过初始化阶段后,build.gradle 文件会对应生成 Poject 对象,settings.gradle 文件会生成 Settings 对象,其实还有 Gradle 对象,每次构建启动时就会创建。
Gradle 是一个构建框架,本身不具备特别强的构建能力,具体构建能力依托于 Gradle Plugin ,比如要打包 APK 就要依托 AGP。AGP 内部通过调用 Android Build Tool 去具体执行诸如编译 class,打包资源等任务。
Gradle Plugin 的是使用首先是引入,就跟我们在项目里需要某个第三方库需要引入一样。在跟目录的 build.gradle 中就可声明这些依赖,然后在构建脚本里声明应用,然后做配置。
//in rootproject/build.gradle
buildscript {
...
dependencies {
classpath:'com.android.tools.build:gradle:x.x.x'
}
}
//in subProject/build.gradle
apply plugin: 'com.android.application'//用于打包生成Apk
android {//构建Apk的配置
}
//in subProject2/build.gradle
apply plugin: 'com.android.library'//用于打包产出AAR
android{ //构建产生aar配置
}
如果在脚本 gradle 脚本中想使用一个第三方库,也需要通过 classpath 引入,然后就可以在脚本中使用了,示例如下。
//in root project build.gradle
buildscript {
dependencies {
classpath: 'com.squareup.okhttp3:okhttp:3.14.9'
}
}
import okhttp3.OkHttpClient
task("checkClasspath").doFirst {
//在脚本中使用引入了的okhttp
def client = new OkHttpClient()
..,
}
以上这种使用 plugin 的方式是分两步【引入+应用】,gradle 还有引入和应用一步搞定的方式。
plugin{ id 'com.android.library' version 'x.x.x' }
默认的这种不需要引入就能应用插件的方式,插件来源只能是 gradle 插件官网https://plugins.gradle.org/,如果想使用自己的插件需要在 pluginManagement 中配置源如下
//settings.gradle
pluginManagement {
repositories {
maven {
url './maven-repo'
}
}
}
Gradel 插件分两种:二进制插件和脚本插件;二进制插件就是被打包成了 jar 包的插件。脚本插件.gradle 文件可以被作为插件使用。这种插件的使用只能通过 apply plugin 方式不能使用 plugin{}的方式。
ext {
mVersion = '1.1.0'
}
apply from: "../config.gradle"
println("mVersion${ext.mVersion}")
task 一般都定义在 plugin 中,我们也可以自己定义 task,给其配置名字,描述,分组,action,依赖关系等。
//build.gradle
project.tasks.register("aTask") {
println 'in configuration phase'
it.description("this is a sample task")
it.dependsOn("hello")
group("build")//IDE右边的Gradle快捷工具栏中,会看到该task被归类到build分组内,方便查找
description "this is a gradle hello sample" //描述
it.doLast {
println("do action >>1") //向当前task的action链路后追加action
}
it.doFirst {
println("do aciton >>2")//向当前task的action链路前查action
}
}
project.tasks.register("hello") {
it.doLast {
println("hello task is excuted-")
}
}
以上只是一个简单的例子,task 的创建使用可以单开一个章节。
本文主要是在一个可能比较高的视角,谈了谈 gradle 相关的概念,生命周期特性,插件 task 等。掌握了这些之后,还有一些更深入更细致的话题值得探索。比如