Gradle是一個(gè)自動(dòng)化的構(gòu)建工具恕汇。要掌握好gradle的用法爽柒,我們需要先對它的生命周期和核心概念有所了解蹋订。
Gradle的核心概念有project和task布讹。Gradle的生命周期包括初始化琳拭、配置、執(zhí)行描验。
下面我們從一個(gè)實(shí)例來講解白嘁,在其生命周期的三個(gè)階段,針對project和task鹉梨,都分別做了什么竞川。
1. 工程目錄結(jié)構(gòu)
2. 執(zhí)行命令
在命令行中執(zhí)行如下命令
$ gradle :projectA:childA1:world
:projectA:childA1:world標(biāo)識了一個(gè)task的路徑负饲。其中:projectA:childA1為project的路徑,world為該project中的一個(gè)task耕魄。
Gradle是如何找到對應(yīng)的project和task的呢?又是在什么時(shí)候執(zhí)行的task呢彭谁?
3. Gradle的生命周期
(1)Initialization-初始化階段
這個(gè)階段會(huì)執(zhí)行settings.gradle文件吸奴,創(chuàng)建project樹。
settings.gradle內(nèi)容如下:
//settings.gradle
println("initialization from settings")
include ":projectA:childA1"
include ":projectA:childA2"
include ":projectB"
:projectA:childA1表示childA1是projectA的子project缠局,根目錄對應(yīng)的是rootProject则奥。根據(jù)settings文件,最后創(chuàng)建的project樹如下:
需要注意的是狭园,project的樹狀關(guān)系一般是和目錄結(jié)構(gòu)保持一致的读处,也可以不一致。比如我們可以在settings中寫
include “:projectA:projectB"
這樣的話唱矛,projectB的父project就變成了projectA档泽。如果這樣寫的話,會(huì)報(bào)錯(cuò)說找不到projectB揖赴,因?yàn)槟J(rèn)情況下Gradle會(huì)在projectA目錄下面找馆匿。我們可以用下面這句話改變project的路徑:
project(":projectA:projectB").projectDir = new File("projectB")
(2)Configuration-配置階段
初始化階段創(chuàng)建完了project,然后便會(huì)按照廣度優(yōu)先的順序燥滑,針對每個(gè)project對象渐北,執(zhí)行其中的build.gradle腳本。
我們的例子中build.gradle的內(nèi)容都一樣铭拧,如下所示:
// build.gradle
println "configuration ${project.path}”
task("hello").doLast{
println("hello from ${project.path}")
}
task("world").doLast {
println("world from ${project.path}")
}
tasks.getByName("world").dependsOn("hello")
task(“hello")其實(shí)就是在調(diào)用:projectA:childA1這個(gè)project對象的task方法赃蛛,這個(gè)project對象就是在前面的初始化階段創(chuàng)建的恃锉。task方法的作用是用來在project中創(chuàng)建一個(gè)task,task的名字為hello呕臂。
這個(gè)腳本中一共創(chuàng)建了兩個(gè)task破托,分別為hello和world。tasks是project中的一個(gè)字段歧蒋,類型為TaskContainer土砂。一個(gè)project 的所有task都會(huì)保存在這個(gè)TaskContainer中。接下來通過task的dependsOn方法谜洽,在hello和world之間創(chuàng)建了依賴關(guān)系萝映。
所有的task會(huì)形成一個(gè)有向無環(huán)圖。
println "configuration ${project.path}”, 這一句在該階段就會(huì)執(zhí)行阐虚,輸出一條日志序臂。
doLast是task的一個(gè)回調(diào)方法,該回調(diào)會(huì)在下面的執(zhí)行階段執(zhí)行实束。
(3)Excution-執(zhí)行階段
配置完了就到了執(zhí)行階段奥秆,我們要執(zhí)行的是projectA:childA1下的world task。gradle會(huì)根據(jù)task的依賴關(guān)系圖咸灿,從前往后執(zhí)行吭练。本例中的world task依賴于hello task,而hello不依賴與任何的task析显,所以先執(zhí)行hello鲫咽,然后再執(zhí)行world。這兩個(gè)task都屬于同一個(gè)project谷异,我們也可以在不同project的task之間建立依賴關(guān)系分尸。比如:
tasks.getByName("world").dependsOn(“:projectB:hello")
task有doFirst和doLast兩個(gè)關(guān)鍵方法,它們可以在task執(zhí)行前后追加命令歹嘹,構(gòu)成了兩個(gè)鏈表箩绍。比如:
tasks.getByName("world").doFirst {
println "first 1"
}
tasks.getByName("world").doFirst {
println "first 2"
}
tasks.getByName("world").doLast {
println "last 1"
}
tasks.getByName("world").doLast {
println "last 2"
}
最后的輸出是
first2
first1
last1
last2
注意是first2在first1之前執(zhí)行
- 輸出結(jié)果
我們最初的例子的輸出結(jié)果如下
從輸出的結(jié)果里面可以驗(yàn)證Gradle生命周期的三個(gè)階段。
參考資料:
Gradle的官網(wǎng)是最好的資料尺上,建議有英文閱讀能力的直接看官網(wǎng)
Gradle用戶手冊:https://docs.gradle.org/current/userguide/userguide.html
Gradle Build Lifecycle: https://docs.gradle.org/current/userguide/build_lifecycle.html#build_lifecycle_events