轉(zhuǎn)自:http://www.cnblogs.com/davenkin/p/gradle-learning-4.html
請(qǐng)通過(guò)以下方式下載本系列文章的Github示例代碼:
git clone https://github.com/davenkin/gradle-learning.git
如果我們將Gradle的Task看作一個(gè)黑盒子,那么我們便可以抽象出輸入和輸出的概念,一個(gè)Task對(duì)輸入進(jìn)行操作,然后產(chǎn)生輸出。比如,在使用java插件編譯源代碼時(shí),輸入即為Java源文件,輸出則為class文件。如果多次執(zhí)行一個(gè)Task時(shí)的輸入和輸出是一樣的,那么我們便可以認(rèn)為這樣的Task是沒(méi)有必要重復(fù)執(zhí)行的。此時(shí),反復(fù)執(zhí)行相同的Task是冗余的,并且是耗時(shí)的。
為了解決這樣的問(wèn)題,Gradle引入了增量式構(gòu)建的概念。在增量式構(gòu)建中,我們?yōu)槊總€(gè)Task定義輸入(inputs)和輸入(outputs),如果在執(zhí)行一個(gè)Task時(shí),如果它的輸入和輸出與前一次執(zhí)行時(shí)沒(méi)有發(fā)生變化,那么Gradle便會(huì)認(rèn)為該Task是最新的(UP-TO-DATE),因此Gradle將不予執(zhí)行。一個(gè)Task的inputs和outputs可以是一個(gè)或多個(gè)文件,可以是文件夾,還可以是Project的某個(gè)Property,甚至可以是某個(gè)閉包所定義的條件。
每個(gè)Task都擁有inputs和outputs屬性,他們的類型分別為TaskInputs和TaskOutputs。在下面的例子中,我們展示了這么一種場(chǎng)景:名為combineFileContent的Task從sourceDir目錄中讀取所有的文件,然后將每個(gè)文件的內(nèi)容合并到destination.txt文件中。讓我們先來(lái)看看沒(méi)有定義Task輸入和輸出的情況:
task combineFileContentNonIncremental {
????def sources = fileTree('sourceDir')
????def destination = file('destination.txt')
????doLast {
????????destination.withPrintWriter {writer ->
????????????sources.each {source ->
????????????????writer.println source.text
????????????}
????????}
????}
}
多次執(zhí)行“gradle combineFileContentNonIncremental”時(shí),整個(gè)Task都會(huì)反復(fù)執(zhí)行,即便在第一次執(zhí)行后我們已經(jīng)得到了所需的結(jié)果。如果該combineFileContentNonIncremental是一個(gè)繁重的Task,那么多次重復(fù)執(zhí)行勢(shì)必造成沒(méi)必要的時(shí)間耗費(fèi)。
這時(shí),我們可以將sources聲明為該Task的inputs,而將destination聲明為outputs,重新創(chuàng)建一個(gè)Task如下:
task combineFileContentIncremental {
????def sources = fileTree('sourceDir')
????def destination = file('destination.txt')
????inputs.dir sources
????outputs.file destination
????doLast {
????????destination.withPrintWriter { writer ->
????????????sources.each {source ->
????????????????writer.println source.text
????????????}
????????}
????}
}
相比之下,后一個(gè)Task只比前一個(gè)Task多了兩行代碼:
inputs.dir sources
outputs.file destination
當(dāng)首次執(zhí)行combineFileContentIncremental時(shí),Gradle會(huì)完整地執(zhí)行該Task。但是緊接著再執(zhí)行一次,命令行顯示:
:combineFileContentIncremental UP-TO-DATE
BUILD SUCCESSFUL
Total time: 2.104 secs
我們發(fā)現(xiàn),combineFileContentIncremental被標(biāo)記為UP-TO-DATE,表示該Task是最新的,Gradle將不予執(zhí)行。在實(shí)際應(yīng)用中,你將遇到很多這樣的情況,因?yàn)镚radle的很多插件都引入了增量式構(gòu)建機(jī)制。
如果我們修改了inputs(即sourceDir文件夾)中的任何一個(gè)文件或刪除掉了destination.txt,當(dāng)調(diào)用“gradle combineFileContentIncremental”時(shí),Gradle又會(huì)重新執(zhí)行,因?yàn)榇藭r(shí)的Task已經(jīng)不再是最新的了。對(duì)于outputs,我們還可以使用upToDateWhen()方法來(lái)決定一個(gè)Task的outputs是否為最新的,該方法接受一個(gè)閉包作為檢查條件,感興趣的讀者可以自行了解。
在下一篇文章中,我們將講到如何自定義Project的Property。