在认识Task之前需要知道Gradle的生命周期分为: 初始化阶段、配置阶段和执行阶段。
Task作为Project的单位,也遵循这个生命周期流程。
Task 的配置、动作与依赖
Task 的配置
task exampleTask {
config1 = "config 1"
config2 = "config 2"
}
在定义task时,我们会在定义后跟上一个闭包,这个闭包将在配置阶段执行,因此我们可以在该闭包中,执行对太任务的属性配置和动作添加等。
注意,配置执行几乎在每次脚本执行流程都将发生。
执行task的命令比较简单,这里就不举例了,可以直接创建一个 build.gradle(每个构建项目下,默认约定的文件名,没有为什么) 进行试验。
gradle 任务名
Task 的动作
与配置不同,Task的动作发生在执行阶段。
动作添加比较常用的有两种方式
task exampleTask << {
println "execute example task"
}
和
task exampleTask {
doLast {
println "execute example task"
}
}
第一种运算符重载的方式在 gralde 5.0 可能将被废除,因此比较推荐的是使用第二种方式,在配置流程中即实现。当然你也可以直接调用 Task 的 doLast 方法直接添加,这里看个人需求而定,只是相对集中的话,方便管理。
Task的依赖
和project 一样,task 也和task 可以产生相互的依赖关系,我们比较常用的场景是,对于 B Task 执行前,我们需要确保 A Task 是执行的,否则将不执行。
这种情况,我们就可以使用Task 的API
dependsOn(tasks: Object...)
在声明Task时,我们可以通过构建器,对Task对象进行简单的配置。
task exampleATask << {
println "execute A Task"
}
task exampleBTask(dependsOn: exampleATask) << {
println "execute B Task"
}
task exampleCTask(dependsOn: [exampleATask,exampleBTask]) << {
println "execute C Task"
}
输出
task exampleATask << {
println "execute A Task"
}
task exampleBTask(dependsOn: exampleATask) << {
println "execute A Task"
}
task exampleCTask(dependsOn: [exampleATask,exampleBTask]) << {
println "execute B Task"
}
我们分别定义A、B、C三个任务,B依赖于A,C依赖于A、B,这里我们执行了C Task,结果输出了:
> Task :SubExample:exampleATask
execute A Task
> Task :SubExample:exampleBTask
execute B Task
> Task :SubExample:exampleCTask
execute C Task
可以看到 Gradle为我们优化了 Task的流程,分别执行了 A、B、C 任务
这里注意下,如果我们在一个依赖中存在多个依赖,在依赖间并不存在可以推断的顺序时,将不保证按声明顺序执行。
task exampleATask << {
println "execute A Task"
}
task exampleBTask << {
println "execute B Task"
}
task exampleCTask << {
println "execute C Task"
}
task exampleDTask(dependsOn: [exampleCTask,exampleBTask,exampleATask]) << {
println "execute D Task"
}
我们运行 exammpleDTask
任务,而输出的是:
> Task :SubExample:exampleATask
execute A Task
> Task :SubExample:exampleBTask
execute B Task
> Task :SubExample:exampleCTask
execute C Task
> Task :SubExample:exampleDTask
execute D Task
dependsOn
的任务关系中,如果前置任务失败,则不会继续执行下面的Task,如果需要保证即使失败也需要执行接下来的任务,则可以使用Task的Api finalizedBy(paths: Object...)
task exampleDTask(dependsOn: [exampleCTask,exampleBTask,exampleATask]) {
finalizedBy exampleETask
doLast {
println "execute D Task"
}
}
以上最后需要确保 exampleETask
执行
自定义Task
在 task 定义中我们经常看到这样定义的任务:
task CopyTask(type:Copy) {
...
}
这里 type
即是 CopyTask
所声明的Task类型,它继承了 Copy Task 一切特性,这相当于我们的继承概念,而 CopyTask 便是其子类,并在task
的声明中产生其实例。
这里我们将 Copy
Task 当做其 Task 的一个模板,因为 copy 任务是经常被复用的,因此将其作为一个内置Task。
那么类似的情况,如果我们也有一个常用的Task模板,我们应该怎么自定义呢。
简单自定义Task
task ExampleSubTask(type:ExampleTask) {
taskParam = "ExampleSubTask"
}
class ExampleTask extends DefaultTask {
String taskParam
@TaskAction
void start(){
println "Example Task start $taskParam"
}
}
这里输出:
> Task :ExampleSubTask
Example Task start ExampleSubTask
这是个简单的例子,我们继承默认的 Task 实现 DefaultTask
,然后在对应的 Task 方法签名上声明 @TaskAction
,作为任务的执行内容。
Tip:如果只是简单的实现Task内容,则可以使用DefaultTask
,其他的细节可参照其父类进行对应的实现。
备注 Api
task依赖
方法 | 说明 | 备注 |
---|---|---|
dependsOn(tasks:Object...) |
动作定义
方法 | 说明 | 备注 |
---|---|---|
doFirst(action: Closure) | ||
doLast(action: Closure) | ||
getActions() |
输入/输出数据声明
方法 | 说明 | 备注 |
---|---|---|
getInputs() | ||
getOutputs() |
getter/setter 属性
方法 | 说明 | 备注 |
---|---|---|
getAnt() | ||
getDescription() | ||
getEnabled() | ||
getGroup() | ||
setDescription(description: String) | ||
setEnabled(enabled: boolean) | ||
setGroup(group: String) |