多種方式創建Gradle任務
在Gradle中我們可以有多種方式在創建任務
//1.直接以一個任務的名字創建任務
def Task myTask1=task(myTask1Do)
myTask1Do.doLast{
println "myTask1Do.doLast"
}
//2.以一個任務的名字+一個對該任務的配置map來創建task實例
def Task myTask2=task(myTask2Do,group:BasePlugin.BUILD_GROUP)
myTask2Do.doLast{
println "myTask2Do=$myTask2Do.group"
}
//3.閉包方式
task myTask3Do{
//閉包中的委託對象是task,description是task的屬性
description '描述'
doLast{
println "myTask3Do:$description"
}
}
多種方式訪問task
//1.task在創建時,會作爲project的屬性添加到project上,所以我們可以通過任務名字來定義和使用task
task mytask
//[]在Groovy是操作符,是getAt()的重載
tasks["mytask"].doLast{
println"mytask"
}
//2.通過路徑訪問
task.findByPath(":多方式訪問Task:mytask").doLast{
println "mytask.findByPath" //找不到返回null
}
task.getByPath(":多方式訪問Task:mytask").doLast{
println "mytask.findByPath" //找不到拋出UnKnownTaskException
}
//當我們拿到task的引用的時候,就可以按照我們的業務邏輯去操縱它,比如配置任務依賴,配置一些屬性
任務的分組和描述
任務的分組其實就是對任務的分類,便於我們對任務進行歸類整理;
任務的描述其實就是說明這個任務有什麼用;
//建議在創建任務的時候對這兩個屬性都要配置
task myTask{
description "description的demo"
group=BasePlugin.BUILD_GROUP
doLast{
println"description:$description,group=$group"
}
}
當我們使用gradle tasks查看任務的時候就可以發現該任務被分類到BuildTasks中去了
使用IDE似乎鼠標懸停到任務上也可以看到描述
操作符的重載
我們都知道<< 和doLast的效果是相同的,但是爲什麼呢?
task <<
//那麼爲什麼left.shift的效果和doLast相同呢?
//源碼:
public Task doLast(final Closure action){
hasCustomActions=true;
if(action==null)
throw new InvalidUserDataException("Action must not be null")
taskMutator.mutate("Task.doLast(Closure)",new Runnable(){
public void run(){
action.add(convertClosureToAction(action))
}
})
}
public Task leftShift(final Closure action){
hasCustomActions=true;
if(action==null)
throw new InvalidUserDataException("Action must not be null")
taskMutator.mutate("Task.leftShift(Closure)",new Runnable(){
public void run(){
action.add(convertClosureToAction(action))
}
})
}
//可以發現這兩個方法的關鍵都是actions.add(),所以他們的效果其實都是一樣的
任務的執行分析
指定Task其實就是遍歷執行actions List
@TaskAction標齊的方法會被作爲action,然後通過task的prependParallelSafeAction被放到actionList中
Task mytask= task mytask1(type:CustomTask)
mytask.doFirst{
println"doFirst"
}
mytask.doLast{
println"doLast"
}
class CustomTask extends DefaultTask{
//TaskAction註解表明是主體方法,只能在類中的定義主體方法
@TaskAction
def doSelf(){
println "doSelf"
}
}
結果
Task執行之前執行doFirst
Task本身執行doSelf
Task執行之後執行doLast
任務的排序
通過task.shouldRunAfter
task.mustRunAfter來控制任務的執行順序
task mytask1 <<{
println "mytask1"
}
task mytask2 <<{
println "mytask2"
}
//依賴的順序不當的話
//Circular dependency between the following tasks:
//強制要求
mytask1.mustRunAfter mytask2
//非強制要求,不一定會按照該順序執行
mytask2.shouldRunAfter mytask1
任務的禁用和啓用
task中有一個enable屬性,默認true,爲false時,執行該方法會提示該任務被跳過
task mytask {
println"mytask"
}
mytask.enabled=false //SKIPPED
onlyIf斷言
Task.onlyIf(Closure),該閉包返回false則跳過
final String ALL="all"
final String MAIN="main"
final String OTHERS='other'
project.ext{
build_apps=ALL
}
task yingyongbao {
println "打應用寶的包"
}
yingyongbao.onlyIf{
def flag=true
if(project.hasProperty("build_apps")){
Object buildType=project.property("build_apps")
if(ALL.equals(buildType)||MAIN.equals(buildType)){
flag=true
}else{
flag=false
}
}
flag
}
task huawei << {
println "打華爲的包"
}
huawei.onlyIf{
def flag=true
if(project.hasProperty("build_apps")){
Object buildType=project.property("build_apps")
if(OTHERS.equals(buildType)||ALL.equals(buildType)){
flag=true
}else{
flag=false
}
}
flag
}
task sixty <<{
println "打360的包"
}
sixty.onlyIf{
def flag=true
if(project.hasProperty("build_apps")){
Object buildType=project.property("build_apps")
if(OTHERS.equals(buildType)||ALL.equals(buildType)){
flag=true
}else{
flag=false
}
}
flag
}
task build
build.dependsOn yingyongbao,huawei,sixty
通過 build_apps 屬性控制我們要打哪些包
#打所有的渠道包
./gradlew :example48:build
./gradlew -Pbuild_apps=all :example48:build
#打首發包
./gradlew -Pbuild_apps=shoufa :example48:build
#打非首發包
./gradlew -Pbuild_apps=exclude_shoufa :example48:build
任務的規則
我們創建的任務都在TaskContainer中,是由其進行管理的.
TaskContainer繼承於NamedDomainObjectCollection,NamedDomainObjectCollection是唯一一個具有唯一不變名字的域的對象的集合,它裏面所有的元素都具有唯一不變的名字:String,所以我們可以通過名字獲取該元素.
添加自定義規則:一個是直接添加一個rule ,一個是通過閉包配置成一個Rule 再添加。
/**
* Adds a rule to this collection. The given rule is invoked when an unknown object is requested by name.
*
* @param rule The rule to add.
* @return The added rule.
*/
Rule addRule(Rule rule);
/**
* Adds a rule to this collection. The given closure is executed when an unknown object is requested by name. The
* requested name is passed to the closure as a parameter.
*
* @param description The description of the rule.
* @param ruleAction The closure to execute to apply the rule.
* @return The added rule.
*/
Rule addRule(String description, Closure ruleAction);
規則的作用:
當查找不到我們要查找到的任務的時候,就會調用我們添加的規則來處理這種異常情況
源碼可知,通過addRule(String,Closure)來配置規則.
當我們執行依賴一個不存在的任務時,Gradle會執行失敗,通過編寫規則我們可以改成打印提示信息