基于 Gradle 5.3.1
incremental task(增量 task):
当输入改变时,可以只处理改变的部分。一个 incremental task 需要实现一个 incremental task action
。
incremental task action(增量 task action):
一个被 @TaskAction 注解的方法,它接收一个 IncrementalTaskInputs
参数。可以在 IncrementalTaskInputs 的 outOfDate
方法里处理改变的 input,在 removed
方法里处理移除的 input。
可以通过 IncrementalTaskInputs.incremental
来判断,Gradle 是否可以判断哪些 input 发生了改变。
Gradle 可以判断哪些 input 发生了变化:
这时,只有改变的 input 会执行 outOfDate action。
Gradle 无法判断哪些 input 发生了改变:
这时,所有的 input 都会执行 outOfDate action。
class IncrementalReverseTask extends DefaultTask {
@InputDirectory
// @InputDirectory 指定一个 property 作为 task 的输入目录
// 目录的 path 或 content 改变后,task 会被认为 out-of-date
File inputDir
@OutputDirectory
// @OutputDirectory 指定一个 property 作为 task 的输出目录
// 目录的 path 或 content 改变后,task 会被认为 out-of-date
File outputDir
@Input
// @Input 注解指定一个 property 作为 task 的输入值,它的值改变后,task 将会认为 out-of-date
// 当使用 File 作为 Input 时,File 的 path 改变才认为 out-of-date;File 的 content 改变不会认为 out-of-date
def inputProperty
@TaskAction
// @TaskAction 注解表示 task 要执行的动作
void execute(IncrementalTaskInputs inputs) {
// inputs.incremental: Gradle 是否能判断 input 的改变
// 如一个或多个 output file 发生改变,Gradle 无法判断哪个 input 发生了改变,inputs.incremental 会返回 false
// 所以的 input 都会认为 out-of-date
println inputs.iscremental ? 'CHANGED inputs considered out of date'
: 'ALL inputs considered out of date'
if (!inputs.incremental)
project.delete(outputDir.listFiles())
// 发生改变的 input 要执行的 action
inputs.outOfDate { change ->
if (change.file.directory) return
println "out of date: ${change.file.name}"
def targetFile = new File(outputDir, change.file.name)
targetFile.text = change.file.text.reverse()
}
// 被移除的 input 要执行的 action
inputs.removed { change ->
if (change.file.directory) return
println "removed: ${change.file.name}"
def targetFile = new File(outputDir, change.file.name)
targetFile.delete()
}
}
}
task incrementalReverse(type: IncrementalReverseTask) {
inputDir = file('inputs')
outputDir = file("$buildDir/outputs")
inputProperty = project.properties['taskInputProperty'] ?: 'original'
}
// 初始化 inputs 目录
task originalInputs() {
doLast {
file('inputs').mkdir()
file('inputs/1.txt').text = 'Content for file 1.'
file('inputs/2.txt').text = 'Content for file 2.'
file('inputs/3.txt').text = 'Content for file 3.'
}
}
执行
$ ./gradlew -q originalInputs incrementalReverse
ALL inputs considered out of date
out of date: 3.txt
out of date: 2.txt
out of date: 1.txt
$ ./gradlew -q incrementalReverse
无输出
task updateInputs() {
doLast {
file('inputs/1.txt').text = 'Changed content for existing file 1.'
file('inputs/4.txt').text = 'Content for new file 4.'
}
}
执行
$ ./gradlew -q updateInputs incrementalReverse
CHANGED inputs considered out of date
out of date: 1.txt
out of date: 4.txt
task removeInput() {
doLast {
file('inputs/3.txt').delete()
}
}
执行
$ ./gradlew -q removeInput incrementalReverse
CHANGED inputs considered out of date
removed: 3.txt
task removeOutput() {
doLast {
file("$buildDir/outputs/1.txt").delete()
}
}
执行
$ ./gradlew -q removeOutput incrementalReverse
ALL inputs considered out of date
out of date: 4.txt
out of date: 2.txt
out of date: 1.txt
$ ./gradlew -q -PtaskInputProperty=changed incrementalReverse
ALL inputs considered out of date
out of date: 4.txt
out of date: 2.txt
out of date: 1.txt