多种方式创建任务
以任务名称创建任务
def Task ex41CreateTask1 = task(ex41CreateTask1)
ex41CreateTask1.doLast {
println "创建方法原型为:Task task (String name) throws InvalidUserDataException"
}
以一个任务名字+一个队该任务配置的Map对象来创建任务
//2.以一个任务名字 + 一个对该任务配置的Map对象来创建任务
def Task ex41CreateTask2 = task(ex41CreateTask2, group:BasePlugin.BUILD_GROUP)
ex41CreateTask2.doLast {
println "创建方法原型为:Task task (Map<String, ?> args, String name) thorws InvalidUserDataException"
println "任务分组:${ex41CreateTask2.group}"
}
Map可用配置如图:
任务名字+闭包配置
task ex41CreateTask3 {
description '演示任务创建'
doLast {
println "创建方法原型为:Task task (String name, Closure configureClosure)"
println "任务描述:${description}"
}
}
TaskContainer创建任务
tasks.create('ex41CreateTask4') {
description '演示任务创建'
doLast {
println "创建方法原型为:Task create (String name, Closure configureClosure) thorws InvalidUserDataException"
println "任务描述:${description}"
}
}
tasks
是Project
对象的属性,其类型是TaskContainer
,我们可以通过它直接创建任务。
多种方式访问任务
通过任务名称直接访问
我们创建的任务都会作为项目(Project)的一个属性,属性名就是任务名,所以我们可以直接通过该任务名称访问和操纵该任务:
task ex42AccessTask1
ex42AccessTask1.doLast {
println 'ex42AccessTask1.doLast'
}
通过TaskContainer
而TaskContainer
就是我们创建任务的集合,在Project中我们可以通过tasks对象访问TaskContainer
,所以我们就可以以访问集合元素的方式访问我们创建的任务。
task ex42AccessTask2
tasks['ex42AccessTask2'].doLast {
println 'ex42AccessTask2.doLast'
}
这里的[]
是Groovy中的一个操作符,a[b]
等价于a.getAt(b)
。
通过路径访问
这种方式有两种,一种是get
,一种是find
,二者区别在于get如果找不到该任务会抛出UnknownTaskException异常,而find会返回Null。
task ex42AccessTask3
tasks['ex42AccessTask3'].doLast {
//通过路径
println "${tasks.findByPath(':ex42AccessTask3')}"
println "${tasks.getByPath(':ex42AccessTask3')}"
println "${tasks.findByPath(':asdfasdfasdf')}"
}
通过名称访问
task ex42AccessTask3
tasks['ex42AccessTask3'].doLast {
//通过名字
println "${tasks.findByName('ex42AccessTask3')}"
println "${tasks.getByName('ex42AccessTask3')}"
println "${tasks.findByName('asdfasdfasdf')}"
}
通过名字访问也分get
和find
两种,二者区别与路径访问方式相同。
不过,通过路径访问的时候,参数值既可以是任务路径也可以是任务名称,而通过任务名字访问则只能是任务名字,不能为路径。
任务分组与描述
任务是可以分组和添加描述的,任务的分组其实就是对该任务的分类,便于我们对任务进行归类整理,而任务的描述则说明了任务有什么作用。
def Task myTask1 = task ex43GroupTask
myTask1.group = BasePlugin.BUILD_GROUP
myTask1.description = "这是一个构建的引导任务"
myTask1.doLast {
println "group:${group}, description:${description}"
}
通过上述代码的配置之后,我们就可以通过gradle tasks查看任务信息了,如下图:
在Android Studio中,侧边栏打开Gradle,我们便可以看到任务的分组情况,将鼠标悬停还可以看到任务的描述。
任务的执行分析
当我们执行一个Task的时候,其实就是执行其拥有的actions列表,这个列表保存在Task对象实例中的actions成员变量中,其类型是一个List。
Task之前执行,Task本身执行,Task之后执行分别被称之为doFirst
/doSelf
/doLast
def Task myTask2 = task ex45CustomTask(type: CustomTask)
myTask2.doFirst {
println '0'
}
myTask2.doLast {
println '2'
}
class CustomTask extends DefaultTask {
@TaskAction
def doself(){
println '1'
}
}
在代码中,我们定义了一种Task类型CustomTask,并声明了一个方法doSelf
,该方法被TaskAction
注解标注,意思是该方法就是Task本身执行要执行的方法。执行该任务,得到下图输出结果:
如前面所说,执行Tasks的时候就是在遍历执行actions List,那么要达到这种执行效果,就必须把doFirst的actions放在List头部,把doSelf的actions放在List中间,把doLast的actions放在List尾部。
当我们使用Task方法创建任务的时候,Gradle会解析其带有TaskAction标注的方法作为其Task本身执行的Action,然后通过Task的prependOarallelSafeAction
方法把该action放在action List中。
在源码中,doFirst和doLast方法就是分别把action添加到了list第一位和末尾。最后这个actions List按顺序就形成了doFirst/doSelf/doLast三部分的Actions,以达到顺序执行的目的。
任务排序
其实并没有真正的像设置优先级或者order顺序的任务排序功能,而是通过任务的shouldRunAfter和mustRunAfter两个方法控制一个任务应该或必须在某个任务之后执行。通过这种方式可以在某些情况下控制任务的执行顺序,而不是通过强依赖的方式。
taskB.shouldRunAfter(taskA)
表示任务B应该在任务A之后执行,这里的应该不是必须,有可能任务顺序并不会按预设的进行。
taskB.mustRunAfter(taskA)
表示任务B必须在任务A之后执行,这里的要求就比较严格了。
task ex46OrderTTask1 {
doLast { println '1' }}task ex46OrderTask2 { doLast { println '2' }}ex46OrderTask1.mustRunAfter ex46OrderTask2```ask1 {
doLast {
println '1'
}
}
task ex46OrderTask2 {
doLast {
println '2'
}
}
ex46OrderTask1.mustRunAfter ex46OrderTask2
执行任务,得到下图输出:
任务的启用和禁用
通过控制task中的enabled
属性,可以控制任务的启用(true)与禁用(false)。如果为false,任务将被跳过,输出也会提示任务被跳过。
任务的onlyIf断言
所谓断言就是一个条件表达式,onlyIf
接收一个闭包作为参数,如果其返回true则该任务执行,否则跳过。
任务规则
了解了这么多,我们再拐回头来看看TaskContainer
。我们知道所有创建的任务都在TaskContainer中,并由其进行管理。所以我们访问任务的时候都是通过TaskContainer访问,而TaskContainer又是继承于NamedDomainObjectCollection
,所以我们说的任务规则其实是NameDomainObjectCollection的规则。
NameDomainObjectCollection是一个具有唯一不变名字的域对象的结合,它里面所有的元素都有一个唯一不变的名字,该名字是String类型,所以我们可以通过名字获取该元素。
参考资料:
《Android Gradle 权威指南》