Gradle基本原理
Gradle 是一種以 Groovy 語言為基礎(chǔ)的自動(dòng)化構(gòu)建工具,一般通過修改 build.gradle 腳本來完成對(duì)項(xiàng)目構(gòu)建的一些設(shè)置,例如依賴管理等等。大多數(shù)情況下,我們只需要稍微修改下 gradle 文件即可完成自己的需求。
android中的 build.gradle 文件,或者其他后綴為 gradle 的文件其實(shí)就是個(gè)配置文件,就好像 xml 一樣,我們?cè)?gradle 文件中修改各種配置參數(shù),Gradle 通過這些參數(shù)來實(shí)例化 Project 等等就像構(gòu)造器一樣。
當(dāng)我們新建一個(gè)項(xiàng)目后,Gradle 默認(rèn)會(huì)生成一些編譯腳本文件,主要有:setting.gradle、build.gradle 以及子項(xiàng)目中的 build.gradle 等等,還會(huì)在當(dāng)前目錄下生成一個(gè) gradle 文件夾,下面分別介紹一些這些文件的作用:
- setting.gradle 用來告訴 gradle 這個(gè)項(xiàng)目包含了那些子項(xiàng)目。
- build.gradle 是默認(rèn)的構(gòu)建腳本,當(dāng)我們?cè)趫?zhí)行 gradle 命令時(shí),會(huì)首先到當(dāng)前目錄下尋找該文件,然后通過該文件的配置實(shí)例化一個(gè) Project 對(duì)象。
- 自動(dòng)生成的 gradle 文件夾是 Gradle 包裝器,其中包含一個(gè) jar 文件和一個(gè) 配置文件,使用這個(gè)包裝器可以讓 Gradle 運(yùn)行在一個(gè)特定的版本上,目的是創(chuàng)造一個(gè)獨(dú)立于系統(tǒng)、系統(tǒng)配置和 Gradle 版本的可靠和可重復(fù)構(gòu)建。
Gradle 中有兩個(gè)重要的概念,分別是 Project 和 Task,Project 表示一個(gè)正在構(gòu)建的項(xiàng)目,而 Task 表示某一個(gè)具體的任務(wù)。
Project
Project 表示正在構(gòu)建的項(xiàng)目,每個(gè) Project 都對(duì)應(yīng)一個(gè)我們?cè)?setting.gradle 中配置的 Project,除此之外還有一個(gè) Root Project。
Project 用來管理、描述當(dāng)前正在構(gòu)建的項(xiàng)目,我們可以通過其中提供的 api 進(jìn)行一些操作來達(dá)到自己的目的。
一個(gè) Project 可以創(chuàng)建新的 Task,添加依賴關(guān)系和配置,并應(yīng)用插件和其他的構(gòu)建腳本。
另外,Project 是通過我們常見的 build.gradle 文件實(shí)例化出來的,我們?cè)?build.gradle 文件中進(jìn)行的各種配置最終都會(huì)應(yīng)用到 Project 中去。
Property
Project 本身提供了一些默認(rèn)的屬性,我們也可以向 Project 中添加自定義的屬性。添加屬性通過 ext 函數(shù)設(shè)置。
[圖片上傳失敗...(image-bbb548-1585911431257)]
Gradle 生命周期
Task 的運(yùn)行與 Gradle 的生命周期息息相關(guān),所以在此之前先介紹一下 Gradle 構(gòu)建的生命周期,無論什么時(shí)候執(zhí)行 Gradle 構(gòu)建,都會(huì)依次運(yùn)行三個(gè)不同的生命周期階段:
-
初始化
在初始化階段,Gradle 會(huì)解析 setting.gradle 文件獲取該項(xiàng)目包含幾個(gè)子項(xiàng)目,然后創(chuàng)建一個(gè) RootProject 以及分別為子項(xiàng)目創(chuàng)建 Project 實(shí)例。 -
配置
初始化完成后進(jìn)入配置階段,此時(shí)會(huì)加載所有 build.gradle 文件配置及插件,然后執(zhí)行所有 Task 的配置代碼塊。 -
執(zhí)行
執(zhí)行指的就是依據(jù)順序執(zhí)行所有 Task 的動(dòng)作。
無論是單獨(dú)運(yùn)行某一個(gè) Task,還是運(yùn)行所有的 Task,Gradle 的生命周期都是固定為上述的三個(gè)步驟,只不過執(zhí)行的時(shí)候會(huì)有選擇的執(zhí)行指定 Task 及其依賴的 Task,這意味著如果一個(gè) Task 設(shè)置了在配置階段執(zhí)行某項(xiàng)任務(wù),即使運(yùn)行了別的 Task,該任務(wù)也會(huì)被執(zhí)行。
Task
Task 定義了一個(gè)當(dāng)前任務(wù)執(zhí)行時(shí)的最小單元,一個(gè) Project 中一般會(huì)存在很多個(gè) Task,通過執(zhí)行這些 Task 來完成整個(gè)項(xiàng)目的構(gòu)建。也就是說,項(xiàng)目構(gòu)建的實(shí)際工作是由一個(gè)個(gè)的 Task 來完成的。
Task 的特征
Task 具備如下幾個(gè)特征。
1. 可以依賴于別的 Task
有時(shí)候我們期望該 Task 在某個(gè) Task 執(zhí)行之后再執(zhí)行,此時(shí)可以使用 dependsOn 方法來設(shè)置依賴關(guān)系,讓 Task 按照順序執(zhí)行。
2. 不同時(shí)機(jī)的 Task 動(dòng)作:onConfig(配置塊)、doFirst、doLast、action
Task 具備自己的執(zhí)行周期,我們可以選擇在不同的時(shí)機(jī)做不同的事情。
onConfig(配置塊) 表示項(xiàng)目的配置階段,也就是上述生命周期中的配置階段,Task 中的配置代碼塊將會(huì)被執(zhí)行。
doFirst 以及 doLast 是指在 Task 的動(dòng)作(action)執(zhí)行前或執(zhí)行后定義的動(dòng)作。
action 指執(zhí)行階段被運(yùn)行的代碼塊。
3. 輸入/輸出
Gradle 通過比較 兩個(gè)構(gòu)建 task 的 inputs 和 outputs 來決定是否是最新的。如果 inputs 和 outputs 沒有發(fā)生變化,則認(rèn)為 task 是最新的,因此,只有當(dāng) inputs 和 outputs 不同時(shí),task 才會(huì)運(yùn)行,否則將會(huì)跳過。
4. 一些 getter/setter 屬性
除此之外,Task 中提供了很多屬性,我們可以通過 get/set 方法來獲取或者設(shè)置。
Task 的創(chuàng)建與使用
下面我們來定義一個(gè) Task:
[圖片上傳失敗...(image-8e7275-1585911431257)]
上述代碼比較簡(jiǎn)單,配置階段會(huì)創(chuàng)建一個(gè)變量,然后在 doFirst 中賦值,doLast 中打印出來,運(yùn)行結(jié)果如下:
> Configure project :
printVersion on config
> Task :printVersion
prepare version
version:1
doLast 方法還有個(gè)等價(jià)的方法:leftShift 可以簡(jiǎn)寫為 <<
printVersion << {
println("on <<")
}
Task 的動(dòng)作除了上面代碼定義的三種外還有一個(gè) action 的動(dòng)作,可以使用注解 @TaskAction 來實(shí)現(xiàn):
class PrintVersion extends DefaultTask{
@TaskAction
void start(){
println("on action")
}
}
Gradle 提供了很多種創(chuàng)建 Task 的方式:
task printVersion{}
project.task("printVersion"){}
project.tasks.create("printVersion"){}
我們可以通過 api 靈活的根據(jù)場(chǎng)景創(chuàng)建 Task。
下面再用一個(gè)例子總結(jié)一下上述內(nèi)容:
project.task("task1"){
println "task1 on config"
doLast {
println "task1 doLast"
}
}
project.tasks.create("task2"){
println "task2 on config"
doLast {
println "task2 doLast"
}
}
task task3{
println "task3 on config"
doLast {
println "task3 doLast"
}
}
task3.dependsOn('task2')//設(shè)置 task3 依賴 task2
輸入命令:gradlew task3,運(yùn)行 task3,結(jié)果如下:
C:\xx\xx\xx>gradlew task3
> Configure project :
task1 on config
task2 on config
task3 on config
> Task :task2
task2 doLast
> Task :task3
task3 doLast
我們?cè)谶\(yùn)行 task3 時(shí),Gradle 會(huì)先初始化然后進(jìn)入配置階段,此時(shí)不管我們運(yùn)行的是哪一個(gè) task,既然構(gòu)建進(jìn)入了配置階段就意味著會(huì)配置所有的 task,所以即使我們只運(yùn)行了 task3,另外兩個(gè) task 也都打印了 on config。
然后進(jìn)入執(zhí)行階段,我們看到執(zhí)行順序是 task2 ——> task3,是因?yàn)榇a中設(shè)置了 task3 依賴 task2,Gradle 在執(zhí)行某個(gè) task 時(shí)會(huì)先執(zhí)行它依賴的 task 鏈表。