多种方式创建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会执行失败,通过编写规则我们可以改成打印提示信息