知识图
一、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的类型
官方文档查看了解即可