Gradle基本原理
Gradle 是一種以 Groovy 語言為基礎的自動化構建工具五鲫,一般通過修改 build.gradle 腳本來完成對項目構建的一些設置岔擂,例如依賴管理等等。大多數情況下塑崖,我們只需要稍微修改下 gradle 文件即可完成自己的需求阔蛉。
android中的 build.gradle 文件弃舒,或者其他后綴為 gradle 的文件其實就是個配置文件,就好像 xml 一樣苗踪,我們在 gradle 文件中修改各種配置參數削锰,Gradle 通過這些參數來實例化 Project 等等就像構造器一樣。
當我們新建一個項目后器贩,Gradle 默認會生成一些編譯腳本文件,主要有:setting.gradle吧黄、build.gradle 以及子項目中的 build.gradle 等等,還會在當前目錄下生成一個 gradle 文件夾拗慨,下面分別介紹一些這些文件的作用:
- setting.gradle 用來告訴 gradle 這個項目包含了那些子項目奉芦。
- build.gradle 是默認的構建腳本,當我們在執(zhí)行 gradle 命令時声功,會首先到當前目錄下尋找該文件,然后通過該文件的配置實例化一個 Project 對象其爵。
- 自動生成的 gradle 文件夾是 Gradle 包裝器筹裕,其中包含一個 jar 文件和一個 配置文件,使用這個包裝器可以讓 Gradle 運行在一個特定的版本上朝卒,目的是創(chuàng)造一個獨立于系統(tǒng)、系統(tǒng)配置和 Gradle 版本的可靠和可重復構建抗斤。
Gradle 中有兩個重要的概念,分別是 Project 和 Task龙宏,Project 表示一個正在構建的項目伤疙,而 Task 表示某一個具體的任務辆影。
Project
Project 表示正在構建的項目黍特,每個 Project 都對應一個我們在 setting.gradle 中配置的 Project蛙讥,除此之外還有一個 Root Project灭衷。
Project 用來管理、描述當前正在構建的項目迫像,我們可以通過其中提供的 api 進行一些操作來達到自己的目的瞳遍。
一個 Project 可以創(chuàng)建新的 Task,添加依賴關系和配置傅蹂,并應用插件和其他的構建腳本。
另外份蝴,Project 是通過我們常見的 build.gradle 文件實例化出來的氓轰,我們在 build.gradle 文件中進行的各種配置最終都會應用到 Project 中去。
Property
Project 本身提供了一些默認的屬性案糙,我們也可以向 Project 中添加自定義的屬性靴庆。添加屬性通過 ext 函數設置。
[圖片上傳失敗...(image-bbb548-1585911431257)]
Gradle 生命周期
Task 的運行與 Gradle 的生命周期息息相關炉抒,所以在此之前先介紹一下 Gradle 構建的生命周期,無論什么時候執(zhí)行 Gradle 構建拿诸,都會依次運行三個不同的生命周期階段:
-
初始化
在初始化階段塞茅,Gradle 會解析 setting.gradle 文件獲取該項目包含幾個子項目,然后創(chuàng)建一個 RootProject 以及分別為子項目創(chuàng)建 Project 實例野瘦。 -
配置
初始化完成后進入配置階段,此時會加載所有 build.gradle 文件配置及插件,然后執(zhí)行所有 Task 的配置代碼塊蠢络。 -
執(zhí)行
執(zhí)行指的就是依據順序執(zhí)行所有 Task 的動作迟蜜。
無論是單獨運行某一個 Task,還是運行所有的 Task娜睛,Gradle 的生命周期都是固定為上述的三個步驟,只不過執(zhí)行的時候會有選擇的執(zhí)行指定 Task 及其依賴的 Task方库,這意味著如果一個 Task 設置了在配置階段執(zhí)行某項任務障斋,即使運行了別的 Task,該任務也會被執(zhí)行垃环。
Task
Task 定義了一個當前任務執(zhí)行時的最小單元,一個 Project 中一般會存在很多個 Task遂庄,通過執(zhí)行這些 Task 來完成整個項目的構建。也就是說秸谢,項目構建的實際工作是由一個個的 Task 來完成的霹肝。
Task 的特征
Task 具備如下幾個特征。
1. 可以依賴于別的 Task
有時候我們期望該 Task 在某個 Task 執(zhí)行之后再執(zhí)行沫换,此時可以使用 dependsOn 方法來設置依賴關系,讓 Task 按照順序執(zhí)行刊棕。
2. 不同時機的 Task 動作:onConfig(配置塊)待逞、doFirst甥角、doLast识樱、action
Task 具備自己的執(zhí)行周期震束,我們可以選擇在不同的時機做不同的事情当犯。
onConfig(配置塊) 表示項目的配置階段,也就是上述生命周期中的配置階段嘉栓,Task 中的配置代碼塊將會被執(zhí)行。
doFirst 以及 doLast 是指在 Task 的動作(action)執(zhí)行前或執(zhí)行后定義的動作侵佃。
action 指執(zhí)行階段被運行的代碼塊奠支。
3. 輸入/輸出
Gradle 通過比較 兩個構建 task 的 inputs 和 outputs 來決定是否是最新的。如果 inputs 和 outputs 沒有發(fā)生變化倍谜,則認為 task 是最新的,因此答毫,只有當 inputs 和 outputs 不同時您旁,task 才會運行,否則將會跳過鹤盒。
4. 一些 getter/setter 屬性
除此之外侦副,Task 中提供了很多屬性,我們可以通過 get/set 方法來獲取或者設置秦驯。
Task 的創(chuàng)建與使用
下面我們來定義一個 Task:
[圖片上傳失敗...(image-8e7275-1585911431257)]
上述代碼比較簡單,配置階段會創(chuàng)建一個變量亲桥,然后在 doFirst 中賦值固耘,doLast 中打印出來,運行結果如下:
> Configure project :
printVersion on config
> Task :printVersion
prepare version
version:1
doLast 方法還有個等價的方法:leftShift 可以簡寫為 <<
printVersion << {
println("on <<")
}
Task 的動作除了上面代碼定義的三種外還有一個 action 的動作厅目,可以使用注解 @TaskAction 來實現:
class PrintVersion extends DefaultTask{
@TaskAction
void start(){
println("on action")
}
}
Gradle 提供了很多種創(chuàng)建 Task 的方式:
task printVersion{}
project.task("printVersion"){}
project.tasks.create("printVersion"){}
我們可以通過 api 靈活的根據場景創(chuàng)建 Task法严。
下面再用一個例子總結一下上述內容:
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')//設置 task3 依賴 task2
輸入命令:gradlew task3深啤,運行 task3路星,結果如下:
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
我們在運行 task3 時,Gradle 會先初始化然后進入配置階段洋丐,此時不管我們運行的是哪一個 task,既然構建進入了配置階段就意味著會配置所有的 task垫挨,所以即使我們只運行了 task3,另外兩個 task 也都打印了 on config哀峻。
然后進入執(zhí)行階段哲泊,我們看到執(zhí)行順序是 task2 ——> task3,是因為代碼中設置了 task3 依賴 task2切威,Gradle 在執(zhí)行某個 task 時會先執(zhí)行它依賴的 task 鏈表。