Gradle 任务

多种方式创建任务

以任务名称创建任务

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}"
	}
}

tasksProject对象的属性,其类型是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')}"
} 

通过名字访问也分getfind两种,二者区别与路径访问方式相同。
不过,通过路径访问的时候,参数值既可以是任务路径也可以是任务名称,而通过任务名字访问则只能是任务名字,不能为路径。

任务分组与描述

任务是可以分组和添加描述的,任务的分组其实就是对该任务的分类,便于我们对任务进行归类整理,而任务的描述则说明了任务有什么作用。

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 权威指南》

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值