一、前言
只有 Task 纔可以在 Gradle 的執行階段去執行(其實質是執行的 Task 中的一系列 Action),所以 Task 的重要性不言而喻。
二、Task
2.1 Task 定義與配置
Task 的定義方式有如下兩種:
Task 的配置方式也有如下兩種:
配置了 group 後可以在 Android Studio 的 Gradle 面板看到對應的 Task Group 及其分組下的 Tasks,如下圖所示:
一般來說都推薦爲我們的 task 配置 group,便於我們查找 task。另外,group 和 descreption 只是最基本的配置,我們看下 Task 的源碼:
可以看到這些屬性都是可以進行配置的,後面會一一講解。
選型 | 描述 | 默認值 |
name | task 名字 | 無,必須指定 |
type | 需要創建的 task Class | DefaultTask |
action | 當 task 執行的時候,需要執行的閉包 closure 或 行爲 Action | null |
overwrite | 替換一個已存在的 task | false |
dependsOn | 該 task 所依賴的 task 集合 | [] |
group | 該 task 所屬組 | null |
description | task 的描述信息 | null |
constructorArgs | 傳遞到 task Class 構造器中的參數 | null |
2.2 Task 執行
上一節我們定義了兩個 task,我們來執行其中一個:
看到上述輸出我們會有個疑問,爲什麼我們執行 helloTask2,但是 helloTask 也被執行輸出了呢?其實很簡單,因爲這兩個 task 都是在 gradle 配置階段執行的,所以我們任何 task 的執行,我們 project 的整個配置代碼都是會執行的,所以這兩個輸出語句都會被執行到。
我們可以通過添加 doFirst 與 doLast 執行動作(Action)爲我們的 task 指定執行階段要執行的代碼,這樣它就只會在 gradle 執行階段去執行。需要注意的是,doFirst 和 doLast 是可以被執行多次的。對於 doFirst 與 doLast 這兩個 Action,它們的作用分別如下所示:
- doFirst:表示 task 執行最開始的時候被調用的 Action。
- doLast:表示 task 將執行完的時候被調用的 Action。
我們來驗證下:
接下來,我們就使用 doFirst 與 doLast 來進行一下實戰,來實現計算 build 執行期間的耗時,其完整代碼如下所示:
2.3 Task 執行順序
指定 Task 的執行順序有三種方式,如下圖所示:
2.3.1 dependsOn 強依賴方式
dependsOn 強依賴的方式可以細分爲靜態依賴和動態依賴,首先看看靜態依賴,如下所示:
taskZ 依賴 taskX 和 taskY:
執行 taskZ 看看:
可以看到被依賴的 task 先執行,這和我們 java 的繼承關係是很相似的。需要注意的是,這裏 taskX 和 taskY 的執行順序是隨機的。
下面我們再來看看動態依賴:
2.3.2 通過Task輸入輸出指定
我們也可以通過 Task 來指定輸入輸出,Task 的輸入輸出對應 TaskInput 和 TaskOutput。下面我們來看一個示例,使用這種方式實現一個自動維護版本發佈文檔的 gradle 腳本,其中輸入輸出相關的代碼如下所示:
首先,我們定義了一個 WirteTask,然後,在註釋1處,指定了輸出文件爲 destFile, 並寫入版本信息到 XML 文件。接着,定義了一個 readTask,並在註釋2處,指定輸入文件爲上一個 task(即 writeTask) 的輸出文件。最後,在註釋3處,使用 dependsOn 將這兩個 task 關聯起來,此時輸入與輸出的順序是會先執行寫入,再執行讀取。這樣,一個輸入輸出的實際案例就實現了。
2.3.3 通過API指定執行順序
除了 dependsOn 的方式,我們還可以在 task 閉包中通過 mustRunAfter 方法指定 task 的依賴順序,mustRunAfter 可以指定一個或多個 task,其示例代碼如下所示:
下面我們在命令行中將 taskX、taskY、taskZ 打亂執行:
可以看到最終的執行順序始終是 taskX、taskY、taskZ。
mustRunAfter 是強制指定順序,另外還有一個 shouldRunAfter 不強制性指定,實際應用中一般不會使用 shouldRunAfter,瞭解一下即可。
2.4 掛接自定義 task 到構建生命週期
我們可以使用 gradle 提供的一系列生命週期 API 去掛接我們自己的 task 到構建生命週期之中,比如使用 afterEvaluate 方法將我們第三小節定義的 writeTask 掛接到 gradle 配置完所有的 task 之後的時刻,示例代碼如下所示:
2.5 Task 類型
除了定義一個新的 task 之外,我們也可以使用 task 的 type 屬性來直接使用一個已有的 task 類型,比如 Gradle 自帶的 Copy、Delete、Sync task 等等。示例代碼如下所示:
更多的 Task 類型我們可以查閱官方文檔。