简介
Gradle生命周期中的hook(钩子)函数是由gradle自动回调的,可以用来帮助我们实现一些功能:
Gradle在生命周期各个阶段都提供了用于回调的钩子函数:
- Gradle初始化阶段:
- 在
settings.gradle
执行完后,会回调Gradle
对象的settingsEvaluated
方法; - 在构建所有工程
build.gradle对
应的Project
对象后,即初始化阶段完毕,会回调Gradle
对象的projectsLoaded
方法。
- 在
- Gradle配置阶段:
- Gradle会循环执行每个工程的
build.gradle
脚本文件; - 在执行当前工程
build.gradle
前,会回调Gradle
对象的beforeProject
方法和当前Project
对象的beforeEvaluate
方法。虽然beforeEvalute
属于project
的生命周期,但是此时buildscript
尚未被加载,所以beforeEvaluate
的设置依然要在init script
或setting script
中进行,不要在build script
中使用project.beforeEvaluate
方法; - 在执行当前工程
build.gradle
后,会回调Gradle
对象的afterProject
方法和当前Project
对象的afterEvaluate
方法; - 在所有工程的
build.gradle
执行完毕后,会回调Gradle
对象的projectsEvaluated
方法; - 在构建
Task
依赖有向无环图后,也就是配置阶段完毕,会回调TaskExecutionGraph
对象的whenReady
方法。
- Gradle会循环执行每个工程的
- Gradle执行阶段:
- Gradle会循环执行
Task
及其依赖的Task
; - 在当前
Task
执行之前,会回调TaskExecutionGraph
对象的beforeTask
方法; - 在当前
Task
执行之后,会回调TaskExecutionGraph
对象的afterTask
方法; - 当所有的
Task
执行完毕后,会回调Gradle
对象的buildFinish
方法。
- Gradle会循环执行
提示:Gradle执行脚本文件的时候会生成对应的实例,主要有如下几种对象:
Gradle
对象:在项目初始化时构建,全局单例存在,只有这一个对象;Project
对象:每一个build.gradle
文件都会被转换成一个Project
对象,类似于maven中的pom.xml
文件;Settings
对象:settings.gradle
会转变成一个settings
对象,和整个项目是一对一的关系,一般只用到include
方法;Task
对象: 从前面的有向无环图中,我们也可以看出,gradle最终是基于Tas
k的,一个项目可以有一个或者多个Task
。
举例
HookAPI验证
以前文所述的GradleTest项目为例,在根项目的settings.gradle
中添加:
gradle.settingsEvaluated {
// 1.settingsEvaluated钩子函数,在初始化阶段完成
println "settingsEvaluated"
}
gradle.projectsLoaded {
// 2.projectsLoaded钩子函数,在初始化阶段完成
println "projectsLoaded"
}
// 声明一个变量:表示当前项目名,在每次执行某个项目的beforeEvaluate方法时先给projectName变量赋值
// 这样方便在gradle.beforeProject和afterProject两个钩子函数使用。
def projectName= ""
gradle.addProjectEvaluationListener(
new ProjectEvaluationListener() {
//3.执行各个project的beforeEvaluate:在配置阶段完成
@Override
void beforeEvaluate(Project project) {
projectName=project.name
println "${project.name} Project beforeEvaluate"
}
// 5.执行各个project的afterEvaluate:在配置阶段完成
@Override
void afterEvaluate(Project project, ProjectState projectState) {
println "${project.name} Project afterEvaluate" }
});
gradle.beforeProject {
// 4.执行各个project的beforeProject:在配置阶段完成
println "${projectName} beforeProject..."
}
gradle.afterProject {
// 6.执行各个project的afterProject:在配置阶段完成
println "${projectName} afterProject..."
}
// 7.所有工程的 build.gradle 执行完毕后,回调Gradle对象的projectsEvaluated方法:在配置阶段完成
def rootProjectName= rootProject.getName()
gradle.projectsEvaluated {
println "${rootProjectName} projectsEvaluated..."
}
// 8.配置阶段完毕后,回调TaskExecutionGraph对象的whenReady方法:在配置阶段完成
gradle.taskGraph.whenReady {
println "${rootProjectName} taskGraph whenReady..."
}
// 9.在当前Task执行之前,会回调TaskExecutionGraph对象的beforeTask方法:在执行阶段完成
gradle.taskGraph.beforeTask {
task -> println "this is the task ${task.name} of the project ${task.getProject().name} beforeTask.."
}
// 10.在当前Task执行之后,会回调TaskExecutionGraph对象的afterTask方法:在执行阶段完成
gradle.taskGraph.afterTask {
task -> println "this is the task ${task.name} of the project ${task.getProject().name} afterTask.."
}
// 11.当所有的 Task 执行完毕后,会回调Gradle对象的buildFinish方法:在执行阶段完成
gradle.buildFinished {
println "${rootProjectName} buildFinished..."
}
在根项目的build.gradle
中添加:
task "A" {
println "root taskA"
doFirst() {
println "root taskA doFirst"
}
doLast() {
println "root taskA doLast"
}
}
在lib1
的build.gradle
中添加:
task "B" {
println "lib1 taskB"
doFirst() {
println "lib1 taskB doFirst"
}
doLast() {
println "lib1 taskB doLast"
}
}
在lib2
的build.gradle
中添加:
//task C在上面
task "C" {
//依赖task D
dependsOn 'D'
println "lib2 taskC"
doFirst() {
println "lib2 taskC doFirst"
}
doLast(){
println "lib2 taskC doLast"
}
}
//task D在下面
task "D" {
println "lib2 taskD"
doFirst() {
println "lib2 taskD doFirst"
}
doLast(){
println "lib2 taskD doLast"
}
}
而后,在根项目中执行gradle C -q
,查看输出结果:
(base) PS D:\develop\ideaWorkspace\GradleTest> gradle C -q
settingsEvaluated
projectsLoaded
GradleTest Project beforeEvaluate
GradleTest beforeProject...
root taskA
GradleTest Project afterEvaluate
GradleTest afterProject...
lib1 Project beforeEvaluate
lib1 beforeProject...
lib1 taskB
lib1 Project afterEvaluate
lib1 afterProject...
lib2 Project beforeEvaluate
lib2 beforeProject...
lib2 taskC
lib2 taskD
lib2 Project afterEvaluate
lib2 afterProject...
lib3 Project beforeEvaluate
lib3 beforeProject...
lib3 Project afterEvaluate
lib3 afterProject...
myplugin Project beforeEvaluate
myplugin beforeProject...
myplugin Project afterEvaluate
myplugin afterProject...
lib1_1 Project beforeEvaluate
lib1_1 beforeProject...
lib1_1 Project afterEvaluate
lib1_1 afterProject...
lib1_2 Project beforeEvaluate
lib1_2 beforeProject...
lib1_2 Project afterEvaluate
lib1_2 afterProject...
GradleTest projectsEvaluated...
GradleTest taskGraph whenReady...
this is the task D of the project lib2 beforeTask..
lib2 taskD doFirst
lib2 taskD doLast
this is the task D of the project lib2 afterTask..
this is the task C of the project lib2 beforeTask..
lib2 taskC doFirst
lib2 taskC doLast
this is the task C of the project lib2 afterTask..
GradleTest buildFinished...
可以看到gradle生命周期的三个阶段,以及每个阶段的hook
函数,以及执行阶段各任务的执行顺序。
我们可以在settings.gradle
中添加监听器,以查看task
的DAG
:
gradle.taskGraph.addTaskExecutionGraphListener(new TaskExecutionGraphListener() {
@Override
void graphPopulated(TaskExecutionGraph taskExecutionGraph) {
taskExecutionGraph.allTasks.forEach(task -> {
println "task $task.name in project $task.project.name"
})
}
})
运行任务C时的输出如下:
(base) PS D:\develop\ideaWorkspace\GradleTest> gradle C -q
......
task D in project lib2
task C in project lib2
......
任务耗时统计
统计各项目或任务的配置和执行阶段运行耗时,可以在根项目的settings.gradle
中添加:
def projectName = rootProject.getName() // 定义项目名
long beginOfSetting = System.currentTimeMillis() // 初始化阶段开始时间
def beginOfConfig // 配置阶段开始时间
def configHasBegin = false // 配置阶段是否开始了
def beginOfProjectConfig = new HashMap() // 存放每个build.gradle执行之前的时间
def beginOfTaskExecute // 执行阶段开始时间
gradle.projectsLoaded {
// 初始化阶段执行完毕
println "${projectName}工程 初始化总耗时 ${System.currentTimeMillis() - beginOfSetting} ms"
}
// build.gradle执行前
gradle.beforeProject {
Project project -> {
if(!configHasBegin){
configHasBegin = true
beginOfConfig = System.currentTimeMillis()
}
beginOfProjectConfig.put(project, System.currentTimeMillis())
}
}
//build.gradle 执行后
gradle.afterProject {
Project project -> {
def begin = beginOfProjectConfig.get(project)
if (project.name == projectName) {
println "根工程${projectName} 配置阶段耗时:${System.currentTimeMillis() - begin} ms"
} else {
println "子工程${project.name} 配置阶段耗时:${System.currentTimeMillis() - begin} ms"
}
}
}
gradle.taskGraph.whenReady {
// 配置阶段完毕
println "整个${projectName}项目在配置阶段总耗时:${System.currentTimeMillis() - beginOfConfig} ms"
beginOfTaskExecute = System.currentTimeMillis()
}
// 执行阶段开始
gradle.taskGraph.beforeTask {
Task task -> {
task.doFirst {
task.ext.beginOfTask = System.currentTimeMillis()
}
task.doLast {
println "${task.name}在执行阶段耗时:${System.currentTimeMillis() - task.ext.beginOfTask} ms"
}
}
}
gradle.buildFinished {
// 执行阶段完毕
println " 执行阶段总耗时:${System.currentTimeMillis() - beginOfTaskExecute} ms"
println " 整个构建过程耗时:${System.currentTimeMillis() - beginOfSetting} ms"
}
执行任务C时的输出结果:
(base) PS D:\develop\ideaWorkspace\GradleTest> gradle C -q
GradleTest工程 初始化总耗时 24 ms
根工程GradleTest 配置阶段耗时:54 ms
子工程lib1 配置阶段耗时:4 ms
子工程lib2 配置阶段耗时:5 ms
子工程lib3 配置阶段耗时:5 ms
子工程myplugin 配置阶段耗时:6 ms
子工程lib1_1 配置阶段耗时:6 ms
子工程lib1_2 配置阶段耗时:5 ms
整个GradleTest项目在配置阶段总耗时:94 ms
D在执行阶段耗时:1 ms
C在执行阶段耗时:1 ms
执行阶段总耗时:12 ms
整个构建过程耗时:278 ms