編寫 Gradle 任務Task
前面幾節課我們先介紹了 Gradle,然后學習了 Groovy 的基礎語法,緊接著介紹了 Android 項目中 Gradle 的配置。我們從配置中可以看出 Gradle 的構建都是基于任務(Task) 的,有了前面幾節的基礎,今天這節課我們來學習一下,怎么樣去定義一個 Gradle 的任務(Task) ,以及Task的生命周期。
1. 聲明 Task
關于 Task 的聲明,我們其實在第三節《構建自己的 Gradle 工程》這一節里面就有所介紹,我們創建 Gradle 項目時就聲明了一個 Task 為 hello,下面我們聲明一個名字為 mTask 的 Task。
task mTask{
doLast{
println "Hello,這是我聲明的Task"
}
}
我們在控制臺執行命令gradle mTask
,我們會看到輸出結果。
$ gradle mTask
Starting a Gradle Daemon (subsequent builds will be faster)
> Task :mTask
Hello,這是我聲明的Task
BUILD SUCCESSFUL in 13s
1 actionable task: 1 executed
一般情況下,我們這樣聲明 Task,其實創建的都是org.gradle.api.DefaultTask
的對象,它是org.gradle.api.Task
的一個實現。DefaultTask
的所有屬性都是私有的,只能通過 get 和 set 方法獲取。
Tips: 其實 Task 的聲明除了上面方法外還有下面 2 種方法:
//Task的第二種聲明方法
task (mTask){
doLast{
println "Hello,這是我聲明的Task"
}
}
//Task的第三種聲明方法
task ('mTask'){
doLast{
println "Hello,這是我聲明的Task"
}
}
2. 給 Task 添加 Action
我們創建一個 Task 后可以根據我們的需要給 Task 添加不同的 Action,上面的“doLast”就是給隊列尾增加一個Action。下面我們先來了解以下,關于 Task 添加 Action 的一些 API:
//在Action 隊列頭部添加Action
Task doFirst(Action<? super Task> action);
Task doFirst(Closure action);
//在Action 隊列尾部添加Action
Task doLast(Action<? super Task> action);
Task doLast(Closure action);
//已經過時了,建議用 doLast 代替
Task leftShift(Closure action);
//刪除所有的Action
Task deleteAllActions();
關于上面的 API,deleteAll 就是刪除所有的 Action,這個我們不用太多講解,而 leftShift 和 doLast 其實是一樣的就是在隊列的尾部增加一個 Action。這個 leftShift API 已經過時,我們建議使用 doLast 代替。關于 doFirst 和 doLast 我們下面通過一個例子來講解:
//創建一個名字為apiTask的 task
task apiTask {
//創建一個 Action , 添加到 Action 列表的頭部
doFirst(new Action<Task>() {
@Override
void execute(Task task) {
println "action1++++++++++"
}
})
//創建一個 Action , 添加到 Action 列表的頭部
doFirst {
println "action2++++++++++"
}
//創建一個 Action , 添加到 Action 列表的尾部
doLast(new Action<Task>() {
@Override
void execute(Task task) {
println "action3++++++++++"
}
})
//創建一個 Action , 添加到 Action 列表的尾部
doLast {
println "action4++++++++++"
}
}
我們在上面的例子的 Task 隊列中,先添加了 action1,然后再在頭部添加了 action2,現在隊列從頭到尾應該是"action2=>action1"然后再在隊尾增加 action3,action4,最終隊列里面從頭至尾依次為:“action2 => action1 => action3 => action4”。我們下面執行 apiTask 任務看看是不是輸出這個順序。
3. 定義 Task 的依賴
關于 Task,它也是可以進行依賴的,Task 聲明依賴的關鍵字是dependsOn
,它支持聲明一個或多個依賴,下面我們看個例子:
task first {
doLast {
println "+++++first+++++"
}
}
task second {
doLast {
println "+++++second+++++"
}
}
//指定多個task依賴
task print(dependsOn :[second,first]) {
doLast {
logger.quiet "指定多個task依賴"
}
}
task third(dependsOn : print) {
doLast {
println '+++++third+++++'
}
}
// //還可以采用這樣的方式
// task third {
// doLast {
// println "+++++third+++++"
// }
// }
// third.dependsOn('print')
我們分別執行gradle print
和 gradle third
命令:
我們從上面的執行結果中可以看出,執行 Task 之前,會先執行它的依賴 Task。
4. Task 的執行順序
我們通過前面dependsOn
關鍵字的定義知道,如果一個 Task 定義了依賴,那么執行這個 Task 之前,它的依賴 Task 需要先執行。這也就是 Gradle 的一個比較優秀思想:聲明在一個給定的 Task 執行之前什么 Task 該被執行,而沒有定義如何去執行。 在 Gradle 中 Task 的執行順序是由輸入/輸出規范自動確定的。既然這么做,肯定是有優點的,那么我們看下它的優點:
優點:
- 由于沒有明確規定,如何去執行,而是規定什么先去執行,這就是支持 Task 并行。這樣可以極大的節約構建的時間成本。
- 我們只需要關注依賴任務,不用去關注依賴鏈上的關系是否發生變化。
5. Gradle 構建的生命周期
前面我們說了 Task 的執行順序,下面我們了解以下 Gradle 構建的生命周期。我們學習 Android 時候我們知道,一個應用(Application)、活動(Activity)、服務(Service)都是有生命周期。同樣今天我們學習的 Gradle 的構建它也是有生命周期的。Gradle 構建的生命周期有三個階段:初始階段,配置階段和運行階段。
5.1 初始階段
在這個階段,Gradle 項目根據正在執行的項目,找出哪些項目依賴需要參與到構建中。在 Android 項目中就是根據setting.gradle
中include
信息,查看有模塊項目參與到構建中。
Tips: 在這個構建階段當前已有的構建腳本代碼都不會被執行。
5.2 配置階段
在這個階段,Gradle 創建了一個模型來代表任務,并參與到項目構建中來。Android 項目中這個階段就是執行build.gradle 腳本文件。
5.3 運行階段
這個階段,就是根據 Gradle 命令傳遞過來的 Task 的名稱,執行相關的依賴任務。Task 的 Action 會在這個階段執行。
下面分享一個小技巧。
Tips: 自定義 Task 的名字最好采用駝峰命名法
我們以我們上面的 apiTask 來定義:
//創建一個名字為apiTask的 task
task apiTask {
//創建一個 Action , 添加到 Action 列表的頭部
doFirst(new Action<Task>() {
@Override
void execute(Task task) {
println "action1++++++++++"
}
})
//創建一個 Action , 添加到 Action 列表的頭部
doFirst {
println "action2++++++++++"
}
//創建一個 Action , 添加到 Action 列表的尾部
doLast(new Action<Task>() {
@Override
void execute(Task task) {
println "action3++++++++++"
}
})
//創建一個 Action , 添加到 Action 列表的尾部
doLast {
println "action4++++++++++"
}
}
前面我們執行命令是:gradle apiTask
,我們使用來駝峰命名法還可以使用gradle aT
來執行。
這個我們其實日常開發中也遇到過,我們打包時執行的gradle aR
相當于gradlew assembleRelease
。
6. 小結
這篇文章我們從 Task 的聲明開始,介紹了如何聲明 Task,再到給 Task 添加 Action,逐步深入,再介紹了 Task 的依賴,執行順序,以及 Gradle 構建的生命周期。通過這一篇文章,大家應該對 Task 有了一定的認識和理解。這將為我們后面組件化和插件化打下基礎。