确保任务执行的顺序
如果我们自定义了多个任务,如何确保执行任务时,按照我们想要的顺序来呢?
按照顺序写任务名
task task1 {
doFirst{ println "task 1 first " }
doLast { println "task 1 last" }
}
task task2{
doFirst{ println "task 2 first " }
doLast { println "task 2 last" }
}
task task3{
doFirst{ println "task 3 first " }
doLast { println "task 3 last" }
}
这里有3个task,如果我们用 顺序执行的方式来写命令行:./gradlew task1 task2 task3
执行的结果就是:
> Task :task1
task 1 first
task 1 last
> Task :task2
task 2 first
task 2 last
> Task :task3
task 3 first
task 3 last
重写mustRunAfter属性
gradle提供了另一种task的属性 mustRunAfter 来改变 执行顺序,比如上面的代码变成:
task task1{
doFirst{ println "task 1 first " }
doLast { println "task 1 last" }
}
task task2{
doFirst{ println "task 2 first " }
doLast { println "task 2 last" }
}
task task3{
doFirst{ println "task 3 first " }
doLast { println "task 3 last" }
}
task1.mustRunAfter task2 // 1必须在2后面执行
再去同样的执行:./gradlew task1 task2 task3, 结果:
> Task :task2
task 2 first
task 2 last
> Task :task1
task 1 first
task 1 last
> Task :task3
task 3 first
task 3 last
重写dependsOn属性
task task1{
doFirst{ println "task 1 first " }
doLast { println "task 1 last" }
}
task task2{
doFirst{ println "task 2 first " }
doLast { println "task 2 last" }
}
task task3{
doFirst{ println "task 3 first " }
doLast { println "task 3 last" }
}
task2.dependsOn task1 // 2必须在 1后面执行
task3.dependsOn task2 // 3必须在2 后面执行
执行代码:gradlew task3
那么我们在执行 task3的时候,也会出现:
> Task :task1
task 1 first
task 1 last
> Task :task2
task 2 first
task 2 last
> Task :task3
task 3 first
task 3 last
这种执行结果,而不再需要在命令行中列出所有的任务名。
而如果注意观察 gradle 的task源代码,就能看出,其实 dependsOn是可以接收多个参数的,所以我们可以这么写:
task3.dependsOn task1,task2
这样就一次性把123的执行顺序定好了。
重写finalizedBy属性
task task1{
doFirst{ println "task 1 first " }
doLast { println "task 1 last" }
}
task task2{
doFirst{ println "task 2 first " }
doLast { println "task 2 last" }
}
task task3{
doFirst{ println "task 3 first " }
doLast { println "task 3 last" }
}
task1.finalizedBy task2
task2.finalizedBy task3
区别是,这次执行代码:gradlew task1,而不是task3.
结果依然相同
> Task :task1
task 1 first
task 1 last
> Task :task2
task 2 first
task 2 last
> Task :task3
task 3 first
task 3 last
相比dependsOn之下,finalizedBy 的方式更加直观,task1后面执行task2,task2后接task3,而执行命令也只需要写 task1就行了。
同样,它也可以接收多个参数:
task3.finalizedBy task2,task1
但是和预想的结果不同,它的效果和 dependsOn接收多个参数刚好相反,执行顺序会变成321.
> Task :task3
task 3 first
task 3 last
> Task :task2
task 2 first
task 2 last
> Task :task1
task 1 first
task 1 last
任务的启动和禁用
如果临时需要禁用某个task,可以改变 它的 enable属性:
task task1{
enabled false // 禁用任务
doFirst{ println "task 1 first " }
doLast { println "task 1 last" }
}
task task2{
doFirst{ println "task 2 first " }
doLast { println "task 2 last" }
}
task task3{
doFirst{ println "task 3 first " }
doLast { println "task 3 last" }
}
task1.finalizedBy task2
task2.finalizedBy task3
以上面的 finalizedBy 定义了123的顺序为例,如果我把task1禁用了,那么它将忽略task1,但是其他task顺序不变。
执行代码:gradlew task1,
> Task :task2
task 2 first
task 2 last
> Task :task3
task 3 first
task 3 last
任务断言
断言是一个条件表达式,可以用于控制任务执行的逻辑,按照实际执行时的情况来调整执行过程。
task task1 {
doFirst { println "task 1 first " }
doLast { println "task 1 last" }
}
task task2 {
doFirst { println "task 2 first " }
doLast { println "task 2 last" }
}
task task3 {
doFirst { println "task 3 first " }
doLast { println "task 3 last" }
}
task1.onlyIf {
if (project.hasProperty("use_task1")) {
def use_task1 = project.property("use_task1")
if (use_task1 == "true") {
true
} else {
false
}
} else {
false
}
}
task3.dependsOn task2, task1
上面代码中,本来我想用命令gradlew task3按照顺序执行123, 但是task1,我用onlyIf动态去控制它是否启用。
我们在执行命令时还可以传入参数:
gradlew -Puse_task1=false task3
注意语法:
-Puse_task1
-P是参数开头,use_task1是参数名 ,-Puse_task1=false task3的意义是,给project添加全局变量use_task1,类型是String
任务规则
当我们去依赖一个任务的时候,有可能这个任务不存在,也有可能是我们自己写错了名称
task myTask {
dependsOn missTask
}
此时,gradle编译时会直接报错。如果我们不想被这种东西阻塞的话,可以加入以下代码:
tasks.addRule("对规则的一个描述,便于调试,查看") {String taskName->
task(taskName){
doLast{
println "该任务 ${taskName} 不存在,请查证后再执行"
}
}
}
这就是任务规则。
所有的Task都会存在于TaskContainer中,我们获取任何任务都是从 TaskContainer中去获取的,它内部有一个findByName方法,
public Task findByName(String name) {
Task task = (Task)super.findByName(name);
if (task != null) {
return task;
} else {
return (Task)super.findByNameWithoutRules(name);
}
}
注意看这个findByNameWithoutRules, 当以名字查找时,如果没找到对应的任务,则会调用 applyRules(name) 来应用我们添加的规则,而Rule本身源码入下:
public interface Rule {
String getDescription();
void apply(String var1);
}
我们需要提供一个描述,再提供一个apply规则。我们在上面提供的规则,其实就是定制了一个特别的任务,替代找不到的那个任务。