在之前的學習中,我們了解到Gradle的構建工作都是由Task組合完成的。本節我們就來介紹一下 Task - 任務。
一、多種方式創建任務
在Gradle中,我們可以有很多種方式來創建任務。為什么有這么多種方式呢?這都依賴於Project提供的快捷方法以及TaskContainer提供的相關Create方法。所以我們閱讀一些Gradle腳本的時候,見到一些不熟悉的創建任務的方法也不要奇怪,一般分為以下幾種方式:
- 第一種:直接以一個任務名字創建任務。
- 第二種:以一個任務名字+一個對該任務配置的Map對象來創建任務。
- 第三種:任務名字+閉包配置。
- 第四種:任務名字+Map參數+閉包。
- 第五種:使用TaskContainer創建任務,調研tasks.create方法創建任務。
二、多種方式訪問任務
其實我們在之前的學習的例子中,我們已經通過了一些方式訪問了任務。下面我們整理一下相關的方式:
- 第一種:我們創建的任務都會作為項目(Project)的一個屬性,屬性名就是任務名,所以我們可以通過該任務名稱訪問和操作該任務。
- 第二種:任務都是通過TaskContainer創建的,TaskContainer就是我們創建任務的集合,在Project中我們可以通過tasks屬性訪問TaskContainer,所以我們可以以訪問集合元素的方式訪問我們的任務。
- 第三種:通過路徑訪問。方式有兩種:get & find,區別在於get的時候找不到就會拋出UnknownTaskException異常,而find在找不到任務的時候會返回null。
- 第四種:通過名稱訪問。通過名字的訪問也有兩種:get & find,它們的區別和上面第三種介紹的一樣。
值得強調的是,通過路徑訪問的時候,參數可以是任務路徑也可以是任務的名字。但是通過名字訪問的時候,參數值只能是任務的名字,不能為路徑。
三、任務排序
其實並沒有真正的任務排序功能,這個排序不像我們想象的通過設置優先級或者Order順序實現,而是通過任務的shouldRunAfter和mustRunAfter這兩個方法,它們可以控制一個任務應該或者一定在某個任務之后執行。通過這種方式,你可以在某些情況下控制任務的執行順序,而不是通過強依賴的方式。
這個功能是非常有用的,比如我們設置的順序是,必須先執行單元測試,然后才能進行打包,這就保證了App的質量。類似的情況還有很多,比如必須要單元測試之后,才能進行集成測試,打包成功之后才能進行部署發布等。
舉例說明:
- taskB.shouleRunAfter(taskA):表示taskB應該在taskA執行之后執行,這里的應該而不是必須。所以有可能任務順序並不會按預設的執行。
- taskB.mustRunAfter(taskA):表示taskB必須在taskA執行之后執行,這個規則相對更加嚴格。
四、任務的onlyIf斷言
斷言就是一個條件表達式。Task有一個onlyIf方法,它接受一個閉包作為參數,如果該閉包返回true,則該任務執行,否則就跳過。這有很多用途,比如控制程序哪些情況下打什么包,什么時候進行單元測試,什么情況下執行單元測試的時候不執行網絡測試。
下面我們以一個打首發包的例子來說明:
final String BUILD_APPS_ALL="all"; final String BUILD_APPS_SHOUFA="shoufa"; final String BUILD_APPS_EXCLUDE_SHOUFA="exclude_shoufa"; task ex48QQRelease << { println "打應用寶的包" } task ex48BaiduRelease << { println "打百度的包" } task ex48HuaweiRelease << { println "打華為的包" } task ex48MiuiRelease << { println "打Miui的包" } task build { group BasePlugin.BUILD_GROUP description "打渠道包" } build.dependsOn ex48QQRelease,ex48BaiduRelease,ex48HuaweiRelease,ex48MiuiRelease ex48QQRelease.onlyIf { def execute = false; if(project.hasProperty("build_apps")){ Object buildApps = project.property("build_apps") if(BUILD_APPS_SHOUFA.equals(buildApps) || BUILD_APPS_ALL.equals(buildApps)){ execute = true }else{ execute = false } }else{ execute = true } execute } ex48BaiduRelease.onlyIf { def execute = false; if(project.hasProperty("build_apps")){ Object buildApps = project.property("build_apps") if(BUILD_APPS_SHOUFA.equals(buildApps) || BUILD_APPS_ALL.equals(buildApps)){ execute = true }else{ execute = false } }else{ execute = true } execute } ex48HuaweiRelease.onlyIf { def execute = false; if(project.hasProperty("build_apps")){ Object buildApps = project.property("build_apps") if(BUILD_APPS_EXCLUDE_SHOUFA.equals(buildApps) || BUILD_APPS_ALL.equals(buildApps)){ execute = true }else{ execute = false } }else{ execute = true } execute } ex48MiuiRelease.onlyIf { def execute = false; if(project.hasProperty("build_apps")){ Object buildApps = project.property("build_apps") if(BUILD_APPS_EXCLUDE_SHOUFA.equals(buildApps) || BUILD_APPS_ALL.equals(buildApps)){ execute = true }else{ execute = false } }else{ execute = true } execute }
在例子中,我們定義了4個渠道,其中百度和應用寶是首發包,另外兩個華為和MiUi不是首發包,通過build_apps屬性來控制我們要打哪些渠道包。
通過這種方式,我們在進行一些相關流程控制上會更加靈活。這在我們使用JenKins等CI工具進行自動化打包和部署的時候就能很好的體現出來。
五、多渠道打包(補充資料)
1.Gradle多渠道打包(動態設定App名稱,應用圖標,替換常量,更改包名,變更渠道):https://www.jianshu.com/p/533240d222d3
2.Android Gradle 多版本多APK打包,修改生成APK名稱:https://blog.csdn.net/aiynmimi/article/details/68944830