Gradle任务基础(2)

227 阅读4分钟

确保任务执行的顺序

如果我们自定义了多个任务,如何确保执行任务时,按照我们想要的顺序来呢?

按照顺序写任务名

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

这种执行结果,而不再需要在命令行中列出所有的任务名。

而如果注意观察 gradletask源代码,就能看出,其实 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后面执行task2task2后接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规则。我们在上面提供的规则,其实就是定制了一个特别的任务,替代找不到的那个任务。