第三十四節(jié) gradle中的project和task

project和task是gradle領(lǐng)域中兩個主要的對象,project為task提供了執(zhí)行的容器和上下文
我們來看張圖


image.png

點(diǎn)進(jìn)去project看下,可以看到它是一個接口


image.png

解釋下gradle的構(gòu)建流程:gradle在構(gòu)建的時候首先會根據(jù)build.gradle配置文件創(chuàng)建一個project實(shí)例,然后執(zhí)行project實(shí)例,build.gradle中的所有代碼都會通過task任務(wù)的方式插入到project中,project實(shí)例可以在配置文件中通過project隱式調(diào)用,什么意思呢?
project.version=""可以簡寫為version=""

什么是task呢,每一個操作都可以定義為一個task任務(wù)

plugins {
    application
    //配置kotlin插件,支持kotlin jvm
    kotlin("jvm")
}

這個application插件中就包含了很多的task

定義任務(wù)

我們可以這樣定義一個任務(wù):

//有兩個參數(shù),第一個是任務(wù)的名稱,第二個是個lambda表達(dá)式,是任務(wù)的具體邏輯
task("這是任務(wù)的名稱",{

    println("任務(wù)的邏輯")

})

定義完成后,在gradle面板中的other任務(wù)集中會多出來個任務(wù)


image.png

雙擊這個任務(wù)


image.png

這兒有個誤區(qū):為什么任務(wù)的邏輯會先于執(zhí)行任務(wù)之前打印出來呢?其實(shí)這個涉及到任務(wù)的生命周期
task生命周期:  先掃描  再執(zhí)行 

可以再寫個任務(wù),看下什么效果

//有兩個參數(shù),第一個是任務(wù)的名稱,第二個是個lambda表達(dá)式,是任務(wù)的具體邏輯
task("這是任務(wù)的名稱",{

    println("任務(wù)的邏輯")

})
task("這是任務(wù)的名稱2",{

    println("任務(wù)的邏輯2")

})
image.png

雙擊任務(wù)2可以看到任務(wù)1也打印了,這就是任務(wù)的掃描


image.png

如果我們想讓任務(wù)在真正執(zhí)行時才執(zhí)行閉包中的邏輯,可以運(yùn)用下doFirst()和doLast()方法

//有兩個參數(shù),第一個是任務(wù)的名稱,第二個是個lambda表達(dá)式,是任務(wù)的具體邏輯
task("這是任務(wù)的名稱",{

    doFirst {
        println("任務(wù)的邏輯")
    }


})
task("這是任務(wù)的名稱2",{

    doFirst {
        println("任務(wù)的邏輯2")
    }
})

現(xiàn)在再次雙擊任務(wù)2


image.png

任務(wù)的依賴

task("做飯",{
    doFirst {
        println("做飯")
    }

}).dependsOn("切菜")

task("買菜",{
    doFirst {
        println("買菜")
    }
})

task("切菜",{
    doFirst {
        println("切菜")
    }
}).dependsOn("買菜")
image.png

雙擊“做飯”,可以看到三個任務(wù)都執(zhí)行了

image.png

還可以對每個任務(wù)添加group屬性對任務(wù)進(jìn)行分組

task("做飯",{
    group="自定義"
    doFirst {
        println("做飯")
    }

}).dependsOn("切菜")

task("買菜",{
    group="自定義"
    doFirst {
        println("買菜")
    }
})

task("切菜",{
    group="自定義"
    doFirst {
        println("切菜")
    }
}).dependsOn("買菜")
image.png

默認(rèn)屬性

task("查看所有默認(rèn)屬性",{
    properties.forEach { t, any ->
        println("key=${t},value=${any}")
    }
})

執(zhí)行任務(wù):


image.png

增量更新

自己的理解:如果一個任務(wù)第二次執(zhí)行的結(jié)果跟第一次執(zhí)行的結(jié)果是相同的,那么第二次執(zhí)行這個任務(wù)時,其實(shí)是沒有必要執(zhí)行的
模擬一個場景:我們統(tǒng)計一下src目錄下所有的文件并且將文件的名字寫入一個新文件中info.txt

task("統(tǒng)計src下所有的文件",{
    doFirst {
        //定義源路徑
        var files=fileTree("src")
        //定義接收文件的路徑
        var infoTxt=File("info.txt")
        files.forEach {
            if(it.isFile)
            {
                //模擬任務(wù)耗時
                Thread.sleep(1000)
                infoTxt.appendText(it.name)
                infoTxt.appendText("\n")
            }
        }

    }
})

src下的所有文件:


image.png

執(zhí)行任務(wù):


image.png

看下生成的info.txt文件


image.png

image.png

我們重復(fù)執(zhí)行”統(tǒng)計src下所有的文件“這個任務(wù),發(fā)現(xiàn)這個任務(wù)總耗時并沒有發(fā)生變化

gradle構(gòu)建之所以優(yōu)秀的原因就是增量更新,但是這兒并體現(xiàn)不出來,因?yàn)樗恢廊蝿?wù)所涉及的文件有沒有發(fā)生變化,我們需要指定輸入源、輸出源,只要這兩個地方一個發(fā)生變化,任務(wù)就有執(zhí)行的必要,否則沒有
? inputs.dir()
? inputs.file()
? outputs.dir()
? outputs.file()
修改下任務(wù)邏輯

task("統(tǒng)計src下所有的文件",{
    //注意位置
    inputs.dir("src")
    outputs.file("info.txt")
    doFirst {
        //定義源路徑
        var files=fileTree("src")
        //定義接收文件的路徑
        var infoTxt=File("info.txt")
        files.forEach {
            if(it.isFile)
            {
                //模擬任務(wù)耗時
                Thread.sleep(1000)
                infoTxt.appendText(it.name)
                infoTxt.appendText("\n")
            }
        }

    }
})

如果不改變輸入源和輸出源多次運(yùn)行:


image.png

發(fā)現(xiàn)任務(wù)耗時為0,其實(shí)就沒有執(zhí)行

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容