gradle学习(14)-任务

最后更新于:2022-04-01 06:51:50

## 1.任务的定义 之前我们定义任务的时候采用的是task + 任务名的方式。例如 ~~~ task hello << { println "hello" } ~~~ 现在再介绍另外两种方式,和上面的定义是等价的。 ~~~ task(hello)<<{ println "hello" } ~~~ ~~~ task('hello')<<{ println "hello" } ~~~ gradle还提供了一个tasks容器来创建任务,通过调用create方法: ~~~ tasks.create(name:'hello')<<{ println "hello" } ~~~ ## 2\. 任务的定位 **将任务看成项目的属性的方式** ~~~ task hello println hello.name println project.hello.name ~~~ ~~~ qianhuis-Mac-mini:0111_1 qianhui$ gradle -q hello hello hello ~~~ **使用tasks容器来定位** ~~~ task hello println tasks.hello.name println tasks['hello'].name ~~~ ~~~ qianhuis-Mac-mini:0111_1 qianhui$ gradle -q hello hello hello ~~~ **tasks.getByPath()方式来获得** ~~~ task hello println tasks.getByPath('hello').path println tasks.getByPath(':hello').path ~~~ ~~~ qianhuis-Mac-mini:0111_1 qianhui$ gradle -q hello :hello :hello ~~~ ## 3.配置任务 ~~~ task myCopy(type:Copy) println myCopy.name ~~~ 定义一个Copy类型名为myCopy的任务。 ~~~ qianhuis-Mac-mini:0111_1 qianhui$ gradle -q myCopy myCopy ~~~ **配置任务的第一种方式** ~~~ Copy myCopy = task(myCopy,type:Copy) myCopy.from 'resources' myCopy.into 'target' myCopy.include('**/*.txt','**/*.xml','**/*.properties') ~~~ 这种方式每次都需要先显式的定义一个对象。比较麻烦。下面有另外一种更好的方式: **配置任务的第二种方式** ~~~ Copy myCopy = task(myCopy,type:Copy) myCopy{ from 'resources' into 'target' include('**/*.txt','**/*.xml','**/*.properties') } ~~~ 这种方式适用于任何任务,第二行myCopy是tasks.getByName的缩写方式。这种方式在配置的时候是有作用的,在执行的时候是不起作用的。 **配置任务的第三种方式** 闭包方式: ~~~ task copy(type:Copy){ from 'resources' into 'target' include('**/*.txt','**/*.xml','**/*.properties') } ~~~ ## 4.配置任务依赖 #### 以任务名的方式定义依赖 依赖其他项目的任务,要想实现该例子,首先要记得settings.gradle在多项目的必要性,所以我们先编写settings.gradle: ~~~ include "projectA","projectB" ~~~ 这样我们的build.gradle就能识别出这两个子项目,接下来在build.gradle中实现依赖其他项目的任务。 ~~~ project('projectA'){ task taskX(dependsOn:':projectB:taskY')<<{ println 'taskX' } } project('projectB'){ task taskY <<{ println 'taskY' } } ~~~ 执行命令: ~~~ qianhuis-Mac-mini:0111_1 qianhui$ gradle -q taskX taskY taskX ~~~ 这是在根项目的build.gradle来定义2个子项目的任务。在正常情况下,我们应该是在各自的项目中,然后来定义项目之间的依赖,所以我们现在分拆taskX 和taskY两个任务到各自的目录中。 在projectA的build.gradle文件中添加: ~~~ task taskX(dependsOn:':projectB:taskY')<<{ println 'taskX' } ~~~ 在projectB 的build.gradle文件中添加: ~~~ task taskY <<{ println 'taskY' } ~~~ 然后将刚才跟目录中的build.gradle中的内容删除,避免造成任务冲突。然后在projectA 下执行命令: ~~~ qianhuis-Mac-mini:projectA qianhui$ gradle -q taskX taskY taskX ~~~ #### 你可以通过task对象来配置依赖 ~~~ task taskX << { println 'taskX' } task taskY <<{ println 'taskY' } taskX.dependsOn taskY ~~~ 输出: ~~~ qianhuis-Mac-mini:0111_1 qianhui$ gradle -q taskX taskY taskX ~~~ #### 使用闭包的方式配置依赖 ~~~ task taskX << { println 'taskX' } taskX.dependsOn{ tasks.findAll{ task -> task.name.startsWith('lib') } } task lib1<<{ println 'lib1' } task lib2 <<{ println 'lib2' } ~~~ 执行任务输出: ~~~ qianhuis-Mac-mini:0111_1 qianhui$ gradle -q taskX lib1 lib2 taskX ~~~ ## 5.任务顺序 (该功能处在孵化阶段,以后可能会改变,所以需要注意) 任务顺序的两个规则:must run after 和 should run after。 当你定义taskX和taskY的关系是必须后执行,那就说明taskX必须在taskY任务执行完才能执行,无论在什么时候。 当你定义taskX和taskY的关系时应该后执行,那就说明不是强制要求的,只是这么做更好点,但是我们应该意识到我们讲should 等价于must还是比较好的。 现在来试试这两种顺序的执行的不同: #### mustRunAfter 在build.gradle定义如下: ~~~ task taskX << { println 'taskX' } task taskY <<{ println 'taskY' } taskX.mustRunAfter taskY ~~~ 上面定义了taskX必须在taskY后执行,但是如果这个时候我们只执行taskX呢? ~~~ qianhuis-Mac-mini:0111_1 qianhui$ gradle -q taskX taskX ~~~ 只执行taskY: ~~~ qianhuis-Mac-mini:0111_1 qianhui$ gradle -q tasky taskY ~~~ 从上面可以看出,单独执行一个任务,是没有什么一样的。那现在我们同时执行两个任务: ~~~ qianhuis-Mac-mini:0111_1 qianhui$ gradle -q tasky taskx taskY taskX qianhuis-Mac-mini:0111_1 qianhui$ gradle -q taskx tasky taskY taskX ~~~ 注意上面我们执行了两次,但是taskX和taskY顺序不一样,但是结果却是一样的,这就说明mustRunAfter奏效了。 #### shouldRunAfter 修改build.gradle文件: ~~~ task taskX << { println 'taskX' } task taskY <<{ println 'taskY' } taskX.shouldRunAfter taskY ~~~ 我们同样执行4次,输出如下: ~~~ qianhuis-Mac-mini:0111_1 qianhui$ gradle -q tasky taskY qianhuis-Mac-mini:0111_1 qianhui$ gradle -q taskx taskX qianhuis-Mac-mini:0111_1 qianhui$ gradle -q taskx tasky taskY taskX qianhuis-Mac-mini:0111_1 qianhui$ gradle -q tasky taskx taskY taskX ~~~ 看出不同了么?我是没看出来,所以官方文档上的例子还是无法说明他们的区别,等有时间再去质问他们吧。 上面需要注意点的是: taskX.shouldRunAfter taskY == taskX.shouldRunAfter(taskY) taskX.mustRunAfter taskY ==  taskX.mustRunAfter(taskY) 其中的括号和空格时等效的。所以我们要了解的是gradle中调用方法的方式多种的。 有2种情况会使上面定义的顺序失效:2个任务之间有依赖和使用 --continue参数 来看看使之失效的例子,上面的例子taskX在taskY后执行,那么这个时候我们定义taskY依赖taskX呢。按我们之前学习依赖中得到的知识,依赖的任务要先执行到。那么看实际执行情况: ~~~ task taskX << { println 'taskX' } task taskY <<{ println 'taskY' } taskY.dependsOn taskX taskX.shouldRunAfter taskY ~~~ ~~~ qianhuis-Mac-mini:0111_1 qianhui$ gradle -q tasky taskx taskX taskY ~~~ 说明依赖的优先级要高于顺序的定义。 ## 6.添加任务描述 build.gradle定义如下: ~~~ task taskX { &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; description 'this a beatiful world' &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; println 'taskX' } task taskY <<{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; description 'this a bad world' &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; println 'taskY' } ~~~ 执行gradle tasks命令输出: ~~~ Other tasks ----------- taskX - this a beatiful world taskY ~~~ 为什么taskX和taskY的有一个没有输出描述信息,在于taskY的定义中有<<,所以没能输出描述信息。那就说明任务的定义中这两种方式还是有一点区别的。
';