Gradle核心:Task及其实战

知识图

在这里插入图片描述

一、Task 定义配置

1、常见创建方式
  • project的task方法
  • project的tasks属性的create方法

(1)task的创建栗子

// project 对象的task方法
// 参数 为task名字 、闭包体
task customTask {
    
    
    print " i am custom task"
}

// 参数参数 为task名字 、闭包体
this.tasks.create(name: "customTask1") {
    
    
    print " i am custom task 1"
}

二者的使用几乎没啥区别

(2)tasks属性

TaskContainer getTasks();
-------------------
TaskContainer 提供的方法:
// 根据路径名,返回task对象,找不到时返回null
Task findByPath(String path); 
// 根据路径名,返回task对象,找不到时抛出异常
Task getByPath(String path) throws UnknownTaskException;
// 创建task
Task create(String name, Closure configureClosure) throws InvalidUserDataException;

1、gradle 其实就是通过task容器来管理project下的所有Task的
2、TaskContainer 提供了task的查找添加等操作
3、无论你怎么添加task,gradle都会在任务阶段构成有向无环图。

2、task的常见配置方式
  • 创建时直接配置
  • 创建代码块中配置()
//1、创建时直接配置
// group :为任务添加分组
// description:为任务添加注释(类似类的注释)
task customTask (group:"myGroup",description:"task study"){
    
    
    print " i am custom task"
}
//2、创建代码块中配置
//通过setXXX方法指定
this.tasks.create(name: "customTask1") {
    
    
    setGroup("newGroup")
    print " i am custom task 1"
}

分组后我们可以在右侧的gradle窗口看到。效果图如下。
如果没有添加分组,则新的任务会被添加到other分组里

在这里插入图片描述

3、task的其他配置

在这里插入图片描述

1、可以看到所有的配置都在这
2、dependsOn指定task之间的依赖
3、overwrite重写task
4、action为task配置要执行的逻辑
ps:先了解下,后面会逐个总结。

二、Task的执行顺序

1、回顾

在这里插入图片描述

前面我们了解了task的定义,接下来先看下回顾,what执行一个任务,怎么另一个任务也执行啦!这时我们回顾下gradle的生命周期:
生命周期分为初始化、配置、执行三个阶段,在build.gradle 书写的代码都会在配置阶段执行那么有什么办法只执行我们想要执行的任务呢?或者说指定在执行阶段执行的task。请看本小节分析。。。

2、指定执行阶段执行Task
  • doFirst:执行阶段中代码块中的代码在所有Task之前先执行
  • doLast:执行阶段代码块中的代码在所有Task之后执行
task mytask1(group:"myGroup1"){
    
    
   print" 分组1内的task1"
   // 闭包内调用
    doFirst {
    
    
        print" 方式1:我在配置阶段任务中先执行"
    }
    // 
   doFirst1 {
    
    
        print" xxx"
    }
}

// task 变量名 方式调用
mytask1.doFirst {
    
    
    print" 方式2:我在配置阶段任务中先执行"
}

在这里插入图片描述

1、可以看出只需添加doXXX方法即可,写在这里的代码是在Gradle执行阶段执行,而不是配置阶段执行
2、通过task变量名调用的doXXX比写在闭包中的先执行(如上方式2优先方式1)
3、多个doXXX时按照顺序执行(如上先执行doFirst,在执行doFirst1)

(1)实战 Task 执行阶段耗时统计

// 计算build时长
def startBuildTime, endBuildTime
this.afterEvaluate {
    
    
        // 保证要找的task 配置完毕
    Project project ->
        def preBuildTask = project.tasks.findByName("preBuild")
        preBuildTask.doFirst {
    
    
            startBuildTime = System.currentTimeMillis()
            print("startTime:$startBuildTime")
        }

        def buildTask = project.tasks.findByName("build")
        buildTask.doLast {
    
    
            endBuildTime = System.currentTimeMillis()
            print("执行阶段build耗费时长:${ endBuildTime - startBuildTime }")
        }
}

注意点:
1、事件的监听保证task的配置完成
2、doFirst、doLast的运用
3、preBuild的执行顺序(执行build之前,系统会preBuild)
4、build任务执行牵涉的任务(参考build文件夹下的.dot文件,用相关软件可以吧这个文件转换为图)

3、task的执行顺序3种指定方式

在这里插入图片描述

1、为task添加依赖方式来指定顺序

为task指定依赖后,执行task时会先执行他所依赖的task

2、为task指定输入输出的方式来指定顺序

每个task都有输入输出(input、output)属性。

3、通过api来指定顺序

(1)通过为Task指定依赖

静态添加task依赖:

定义task时知道要添加那些task,直接添加。

task  taskA{
    
    
    doLast {
    
    
        print("任务A")
    }
}

task  taskB{
    
    
    doLast {
    
    
        print("任务B")
    }
}

// 添加依赖
task  taskC(dependsOn:["taskA","taskB"]){
    
    
    doLast {
    
    
        print("任务C")
    }
}



在这里插入图片描述

1、如上通过dependsOn来指定,上面指定了多个依赖使用了集合,其实还可以指定一个依赖,值是字符串即可。
2、TaskA和TaskB的执行顺序是随机的
3、上面方式是声明时指定的依赖其实。还可以单独指定依赖:taskC.dependsOn(taskA,TaskB)

动态添加task依赖:

task myTask {
    
    
   dependsOn tasks.findAll {
    
    
     Task task->return task.name.startsWith("lib")
   }
    doLast {
    
    
        println("我是MyTask")
    }
}

task libA {
    
    
    doLast {
    
    
        println("我是libA")
    }

}
task libB {
    
    
    doLast {
    
    
        println("我是libB")
    }
}

task nolib {
    
    
    doLast {
    
    
        println("我是nolib")
    }
}

依赖 以 lib 开头的任务

(2)通过为Task指定输入输出

在这里插入图片描述

task libA {
    
    
    inputs.file(file("./a.txt")) // 获得输入文件(libB写好的文件)
    doLast {
    
    
        def file = inputs.getFiles().getSingleFile()
        print(file.text)
    }

}
task libB {
    
    
    // 要输入的文件
    inputs.property("key", "value")
    // 写入的地址
    outputs.dir("./a.txt")
    doLast {
    
    
        def data = inputs.getProperties()
        File file = outputs.getFiles().getSingleFile()
        // todo 其他逻辑处理
    }
}

如上通过输入输出的指定两个任务就建立的先后的关系:libB先与libA执行

(3)通过特定api指定-mustRunAfter

task libC {
    
    
    mustRunAfter(libB) // 任务执行与libB之后
    doLast {
    
    
        // todo
    }
}

扩展:
1、想使用自定义的xxx.gradle 文件,只需当前工程引用下,就可以使用这个gradle的文件啦。(apply from: rootProject.file(“xxx.gradle”))
2、apply plugin: ‘com.android.application’ 就是使用了系统的application的任务,plugin类似java的jar包,jar包放了java类,plugin放了一些Task。提供使用

四、Task的类型

官方文档查看了解即可

The end

猜你喜欢

转载自blog.csdn.net/qq_38350635/article/details/103000839
今日推荐