project和task是gradle领域中两个主要的对象,project为task提供了执行的容器和上下文
我们来看张图

点进去project看下,可以看到它是一个接口

解释下gradle的构建流程:gradle在构建的时候首先会根据build.gradle配置文件创建一个project实例,然后执行project实例,build.gradle中的所有代码都会通过task任务的方式插入到project中,project实例可以在配置文件中通过project隐式调用,什么意思呢?
project.version=""可以简写为version=""
什么是task呢,每一个操作都可以定义为一个task任务
plugins {
application
//配置kotlin插件,支持kotlin jvm
kotlin("jvm")
}
这个application插件中就包含了很多的task
定义任务
我们可以这样定义一个任务:
//有两个参数,第一个是任务的名称,第二个是个lambda表达式,是任务的具体逻辑
task("这是任务的名称",{
println("任务的逻辑")
})
定义完成后,在gradle面板中的other任务集中会多出来个任务

双击这个任务

这儿有个误区:为什么任务的逻辑会先于执行任务之前打印出来呢?其实这个涉及到任务的生命周期
task生命周期: 先扫描 再执行
可以再写个任务,看下什么效果
//有两个参数,第一个是任务的名称,第二个是个lambda表达式,是任务的具体逻辑
task("这是任务的名称",{
println("任务的逻辑")
})
task("这是任务的名称2",{
println("任务的逻辑2")
})

双击任务2可以看到任务1也打印了,这就是任务的扫描

如果我们想让任务在真正执行时才执行闭包中的逻辑,可以运用下doFirst()和doLast()方法
//有两个参数,第一个是任务的名称,第二个是个lambda表达式,是任务的具体逻辑
task("这是任务的名称",{
doFirst {
println("任务的逻辑")
}
})
task("这是任务的名称2",{
doFirst {
println("任务的逻辑2")
}
})
现在再次双击任务2

任务的依赖
task("做饭",{
doFirst {
println("做饭")
}
}).dependsOn("切菜")
task("买菜",{
doFirst {
println("买菜")
}
})
task("切菜",{
doFirst {
println("切菜")
}
}).dependsOn("买菜")

双击“做饭”,可以看到三个任务都执行了

还可以对每个任务添加group属性对任务进行分组
task("做饭",{
group="自定义"
doFirst {
println("做饭")
}
}).dependsOn("切菜")
task("买菜",{
group="自定义"
doFirst {
println("买菜")
}
})
task("切菜",{
group="自定义"
doFirst {
println("切菜")
}
}).dependsOn("买菜")

默认属性
task("查看所有默认属性",{
properties.forEach { t, any ->
println("key=${t},value=${any}")
}
})
执行任务:

增量更新
自己的理解:如果一个任务第二次执行的结果跟第一次执行的结果是相同的,那么第二次执行这个任务时,其实是没有必要执行的
模拟一个场景:我们统计一下src目录下所有的文件并且将文件的名字写入一个新文件中info.txt
task("统计src下所有的文件",{
doFirst {
//定义源路径
var files=fileTree("src")
//定义接收文件的路径
var infoTxt=File("info.txt")
files.forEach {
if(it.isFile)
{
//模拟任务耗时
Thread.sleep(1000)
infoTxt.appendText(it.name)
infoTxt.appendText("\n")
}
}
}
})
src下的所有文件:

执行任务:

看下生成的info.txt文件


我们重复执行”统计src下所有的文件“这个任务,发现这个任务总耗时并没有发生变化
gradle构建之所以优秀的原因就是增量更新,但是这儿并体现不出来,因为它不知道任务所涉及的文件有没有发生变化,我们需要指定输入源、输出源,只要这两个地方一个发生变化,任务就有执行的必要,否则没有
• inputs.dir()
• inputs.file()
• outputs.dir()
• outputs.file()
修改下任务逻辑
task("统计src下所有的文件",{
//注意位置
inputs.dir("src")
outputs.file("info.txt")
doFirst {
//定义源路径
var files=fileTree("src")
//定义接收文件的路径
var infoTxt=File("info.txt")
files.forEach {
if(it.isFile)
{
//模拟任务耗时
Thread.sleep(1000)
infoTxt.appendText(it.name)
infoTxt.appendText("\n")
}
}
}
})
如果不改变输入源和输出源多次运行:

发现任务耗时为0,其实就没有执行
网友评论