Gradle知识学习

Cheer Up!

Gradle生命周期

  1. 初始化阶段

  2. 配置阶段

  3. 执行阶段

1. 初始化阶段

Gradle根据setting.gradle文件的配置为项目创建Project实例。

2. 配置阶段

​ Gradle构造一个模型表示任务,并参与构建中来。增量式构建决定我们的task是否需要运行。配置阶段完成后。整个build的project以及内部的Task关系就确定了。这个阶段非常适合为项目或指定task设置所需要的配置数据。配置阶段的实质为解析每个被加入构建项目的build.gradle脚本,比如通过apply方法引入插件,为插件扩展属性进行配置等等。。。。

​ 注意:项目的每一次构建的任何配置代码都可以被执行-即使你只运行gradle tasks。

3. 执行阶段

​ 在执行阶段,所有的task按照配置阶段规定好的顺序,一次执行。我们通常会在根据任务执行的生命周期去动态在合适的位置插入我们自己的运行期间执行的代码断。

​ 许多生命周期方法都被定义在了Gradle 和 Project方法里面。不要害怕使用生命周期钩子,它相反就是为了给开发者使用提供方便而设计出来的。


生命周期监听方法

​ 如果我们想在Gradle特定的阶段去Hook指定的任务,那么我们需要对如何监听生命周期的回调有一些了解。

​ Gradle和Project对象提供了一些方法供我们使用:

​ 生命周期监听的设置有两个方法:

 1. 实现一个特定的监听接口
 2. 提供一个用于在收到通知时执行的闭包。

Project提供的一些生命周期方法:

  • afterEvaluate(closure) , atferEvaluate(action)

  • beforeEvaluate(closure) , beforeEvaluate(action)

  • *Gradle**提供的一些生命周期方法:

  • afterProject(closure) , afterProject(action)

  • beforeProject(closure) , beforeProject(action)

  • buildFinished(closure) , buildFinished(action)

  • projectsEvaluated(closure) , projectsEvaluated(action)

  • projectsLoaded(closure) , projectsLoaded(action)

  • settingsEvaluated(closure) , settingsEvaluated(action)

  • addBuildListener(buildListener)

  • addListener(listener)

  • addProjectEvaluationListener(listener)

    可以看到每个方法都有两个不同参数,一个接收闭包,一个接收Action作为回调。注意,一些生命周期的方法只会在合适的位置上才会发生。

beforeEvaluate

beforeEvalute() 在project开始配置前调用。这个方法很容易误用,你要是直接在子模块的build.gradle中使用肯定是不会被调用的。应为project都没配置好所以也就什么事情也不会发生。这个代码块的添加只能放在父工程的build.gradle中:

1
2
3
4
5
this.project.subprojects { sub ->
sub.beforeEvaluate { project
println("### Evaluate before of "+project.path)
}
}

afterEvaluate

afaterEvaluate() 是一般比较常见的一个配置,只要在project配置成功均会被调用,不论在父模块还是在子模块。

1
2
3
project.afterEvaluate { pro->
println("### Evaluate after of " + pro.path)
}

afterProject

设置一个project配置完成后即执行的闭包或者action。

afterPeoject在配置参数失败后传入两个参数,前者当前project,后者显示失败信息。

1
2
3
4
5
6
7
this.getGradle().afterProject{project,projectState->
if(projectState.failure){
println("Evaluate afterProject of "+ project + "Falued")
}else{
println("Evaluate afterPeoject of "+ project + "Successed")
}
}

beforeProject

设置一个project配置前执行的闭包,子模块的该方法声明在root project中回调才会执行,root project的该方法声明在setting.gradle中才执行。

1
2
3
gradle.beforeProject { p ->
println("Evaluation beforeProject"+p)
}

buildFinished

构建结束时的回调,此时所有的任务都执行完毕,一个构建结果的对象BuildResult作为参数传递给闭包。

1
2
3
gradle.buildFinished { r ->
println("buildFinished "+r.failure)
}

projectEvaluated

所有的peoject都配置完成后的回调,此时,所有的project都配置完毕,准备开始生成task图。gradle对象作为参数传递给闭包。

1
2
3
gradle.projectsEvaluated {gradle ->
println("projectsEvaluated")
}

projectsLoaded

当setting中的所有project都创建好时执行闭包回调,gradle对象会作为参数传递给闭包。这个方法比较特殊,只有声明在适当的位置才会发生,如果这个声明周期挂接闭包声明在build.gradle文件,那么将不会发生这个事件。应为项目创建发生在初始阶段。放在setting.gradle中是可以执行的。

1
2
3
gradle.projectsLoaded {gradle ->
println("@@@@@@@ projectsLoaded")
}

settingsEvaluated

当 settings.gradle 加载并配置完毕后执行闭包回调,setting对象已经配置好并且准备开始加载构建 project。这个回调在 build.gradle 中声明也是不起作用的,在 settings.gradle 中声明是可以的。

1
2
3
gradle.settingsEvaluated {
println("@@@@@@@ settingsEvaluated")
}

前面说过设置监听还有两个方法,通过接口监听。

addProjectEvaluationListener

1
2
3
4
5
6
7
8
9
10
gradle.addProjectEvaluationListener(new ProjectEvaluationListener() {
@Override
void beforeEvaluate(Project project) {
println " add project evaluation lister beforeEvaluate,project path is: "+project
}
@Override
void afterEvaluate(Project project, ProjectState state) {
println " add project evaluation lister afterProject,project path is:"+project
}
})

addListener

添加一个实现来listener接口的对象到build

addBuildListener

添加一个BuildListener对象到Build

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
gradle.addBuildListener(new BuildListener() {
@Override
void buildStarted(Gradle gradle) {
println("### buildStarted")
}
@Override
void settingsEvaluated(Settings settings) {
println("### settingsEvaluated")
}
@Override
void projectsLoaded(Gradle gradle) {
println("### projectsLoaded")
}
@Override
void projectsEvaluated(Gradle gradle) {
println("### projectsEvaluated")
}
@Override
void buildFinished(BuildResult result) {
println("### buildFinished")
}
})

Task执行图

在配置时,Gradle决定在执行阶段要运行的task顺序,他们依赖关系的内部结构被建模为一个有向无环图。我们称之为task执行图。它可以用TaskExecutionGraph来表示。可以通过gradle.taskGraph来获取。在TaskExecutationGraph中也可以设置一些Task生命周期回到。

  • addTaskExecutationGraphListener(TaskExecutionGraphListener listener)
  • addTaskExecutionListener(TaskExecutionListener listener)
  • afterTask(Action action),afterTask(Closure closure)
  • beforeTask(Action action),beforeTask(Closure closure)
  • whenReady(Action action),whenReady(Closure closure)

addTaskExecutionGraphListener

添加 task 执行图的监听器,当执行图配置好会执行通知。

1
2
3
4
5
6
gradle.taskGraph.addTaskExecutionGraphListener(new TaskExecutionGraphListener() {
@Override
void graphPopulated(TaskExecutionGraph graph) {
println("@@@ gradle.taskGraph.graphPopulated ")
}
})

addTaskExecutionListener

添加 task 执行监听器,当 task 执行前或者执行完毕会执行回调发出通知。

1
2
3
4
5
6
7
8
9
10
gradle.taskGraph.addTaskExecutionListener(new TaskExecutionListener() {
@Override
void beforeExecute(Task task) {
println("@@@ gradle.taskGraph.beforeTask "+task)
}
@Override
void afterExecute(Task task, TaskState state) {
println("@@@ gradle.taskGraph.afterTask "+task)
}
})

afterTask

1
2
3
gradle.taskGraph.afterTask { task ->
println("### gradle.taskGraph.afterTask "+task)
}

beforeTask

1
2
3
gradle.taskGraph.beforeTask { task ->
println("### gradle.taskGraph.beforeTask "+task)
}

whenReady

设置一个 task 执行图准备好后的闭包或者回调方法。
该 taskGrahp 作为参数传递给闭包。

1
2
3
gradle.taskGraph.whenReady { taskGrahp ->
println("@@@ gradle.taskGraph.whenReady ")
}

生命周期执行顺序

我们通过在生命周期回调中添加打印的方法来看下顺序:

1
2
3
4
5
6
7
8
9
task hello {
doFirst {
println '*** task hello doFirst'
}
doLast {
println '*** task hello doLast'
}
println '*** config task hello'
}

为了保证生命周期的各个回调方法都被执行,我们在 settings.gradle 中添加各个回调方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
gradle.addBuildListener(new BuildListener() {
@Override
void buildStarted(Gradle gradle) {
println("### gradle.buildStarted")
}

@Override
void settingsEvaluated(Settings settings) {
println("### gradle.settingsEvaluated")
}

@Override
void projectsLoaded(Gradle gradle) {
println("### gradle.projectsLoaded")
}

@Override
void projectsEvaluated(Gradle gradle) {
println("### gradle.projectsEvaluated")
}

@Override
void buildFinished(BuildResult result) {
println("### gradle.buildFinished")
}
})

gradle.afterProject { project,projectState ->
if(projectState.failure){
println "### gradld.afterProject "+project+" FAILED"
} else {
println "### gradle.afterProject "+project+" succeeded"
}
}

gradle.beforeProject { p ->
println("### gradle.beforeProject "+p)
}

gradle.allprojects(new Action<Project>() {
@Override
void execute(Project project) {
project.beforeEvaluate { project
println "### project.beforeEvaluate "+project
}
project.afterEvaluate { pro ->
println("### project.afterEvaluate " + pro)
}
}
})



gradle.taskGraph.addTaskExecutionListener(new TaskExecutionListener() {
@Override
void beforeExecute(Task task) {
if (task.name.equals("hello")){
println("@@@ gradle.taskGraph.beforeTask "+task)
}
}

@Override
void afterExecute(Task task, TaskState state) {
if (task.name.equals("hello")){
println("@@@ gradle.taskGraph.afterTask "+task)
}
}
})

gradle.taskGraph.addTaskExecutionGraphListener(new TaskExecutionGraphListener() {
@Override
void graphPopulated(TaskExecutionGraph graph) {
println("@@@ gradle.taskGraph.graphPopulated ")
}
})

gradle.taskGraph.whenReady { taskGrahp ->
println("@@@ gradle.taskGraph.whenReady ")
}

执行 task info

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
./gradlew hello
### gradle.settingsEvaluated
### gradle.projectsLoaded

> Configure project :
### gradle.beforeProject root project 'TestSomething'
### project.beforeEvaluate root project 'TestSomething'
### gradle.afterProject root project 'TestSomething' succeeded
### project.afterEvaluate root project 'TestSomething'

> Configure project :app
### gradle.beforeProject project ':app'
### project.beforeEvaluate project ':app'
*** config task hello
### gradle.afterProject project ':app' succeeded
### project.afterEvaluate project ':app'

> Configure project :common
### gradle.beforeProject project ':common'
### project.beforeEvaluate project ':common'
### gradle.afterProject project ':common' succeeded
### project.afterEvaluate project ':common'

### gradle.projectsEvaluated
@@@ gradle.taskGraph.graphPopulated
@@@ gradle.taskGraph.whenReady

> Task :app:hello
@@@ gradle.taskGraph.beforeTask task ':app:hello'
*** task hello doFirst
*** task hello doLast
@@@ gradle.taskGraph.afterTask task ':app:hello'

BUILD SUCCESSFUL in 1s
1 actionable task: 1 execu

因此,生命周期回调的执行顺序是:

  • gradle.settingsEvaluated->
    gradle.projectsLoaded->
    gradle.beforeProject->
    project.beforeEvaluate->
    gradle.afterProject->
    project.afterEvaluate->
    gradle.projectsEvaluated->
    gradle.taskGraph.graphPopulated->
    gradle.taskGraph.whenReady->
    gradle.buildFinished

非常好的博客:https://www.heqiangfly.com/2016/03/18/development-tool-gradle-lifecycle/