基於 Gradle 5.3.1
文章目錄
一、概述
1.1 incremental task 與 incremental task action
incremental task(增量 task):
當輸入改變時,可以只處理改變的部分。一個 incremental task 需要實現一個 incremental task action
。
incremental task action(增量 task action):
一個被 @TaskAction 註解的方法,它接收一個 IncrementalTaskInputs
參數。可以在 IncrementalTaskInputs 的 outOfDate
方法裏處理改變的 input,在 removed
方法裏處理移除的 input。
1.2 判斷標準
可以通過 IncrementalTaskInputs.incremental
來判斷,Gradle 是否可以判斷哪些 input 發生了改變。
Gradle 可以判斷哪些 input 發生了變化:
- 當 task 的執行環境與上次執行時相比,只有 input 發生了改變,那改變的 input 就會被認爲 out-of-date。
這時,只有改變的 input 會執行 outOfDate action。
Gradle 無法判斷哪些 input 發生了改變:
- 沒有前一次執行的記錄
- 使用不同版本的 Gradle 執行
- upToDateWhen 返回了 false
- 一個 input 屬性發生了變化
- 一個或多個 output 發生了變化
這時,所有的 input 都會執行 outOfDate action。
二、執行實例
2.1 IncrementalReverseTask 類
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()
}
}
}
2.2 IncrementalReverseTask 類型的 task
task incrementalReverse(type: IncrementalReverseTask) {
inputDir = file('inputs')
outputDir = file("$buildDir/outputs")
inputProperty = project.properties['taskInputProperty'] ?: 'original'
}
2.3 第一次執行
// 初始化 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
2.4 無改變第二次執行
$ ./gradlew -q incrementalReverse
無輸出
2.5 更新 input 後執行
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
2.6 移除 input 後執行
task removeInput() {
doLast {
file('inputs/3.txt').delete()
}
}
執行
$ ./gradlew -q removeInput incrementalReverse
CHANGED inputs considered out of date
removed: 3.txt
2.7 移除 output 後執行
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
2.8 改變 input 屬性後執行
$ ./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