文章目录

  • 简介
  • 定义task
  • tasks 集合类
  • Task 之间的依赖
  • 定义task之间的顺序
  • 给task一些描述
  • task的条件执行
  • task rule
  • Finalizer tasks
  • 总结

简介

在之前的文章中,我们讲到了如何使用gradle创建一个简单的task,以及task之间怎么依赖,甚至使用了程序来创建task。在本文中,我们会更加深入的去了解一下gradle中的task。

定义task

定义一个task可以有很多种方式,比如下面的使用string作为task的名字:

task('hello') {doLast {println "hello"}
}task('copy', type: Copy) {from(file('srcDir'))into(buildDir)
}

还可以使用tasks容器来创建:

tasks.create('hello') {doLast {println "hello"}
}tasks.create('copy', Copy) {from(file('srcDir'))into(buildDir)
}

上面的例子中,我们使用tasks.create方法,将新创建的task加到tasks集合中。

我们还可以使用groovy特有的语法来定义一个task:

task(hello) {doLast {println "hello"}
}task(copy, type: Copy) {from(file('srcDir'))into(buildDir)
}

tasks 集合类

上面我们在创建task的时候,使用了tasks集合类来创建task。

实际上,tasks集合类是一个非常有用的工具类,我们可以使用它来做很多事情。

直接在build文件中使用tasks,实际上是引用了TaskContainer的一个实例对象。我们还可以使用 Project.getTasks() 来获取这个实例对象。

我们看下TaskContainer的定义:

public interface TaskContainer extends TaskCollection<Task>, PolymorphicDomainObjectContainer<Task>

从定义上,我们可以看出TaskContainer是一个task的集合和域对象的集合。

taskContainer中有四类非常重要的方法:

第一类是定位task的方法,有个分别是findByPath和getByPath。两个方法的区别就是findByPath如果没找到会返回null,而getByPath没找到的话会抛出UnknownTaskException。

看下怎么使用:

task helloprintln tasks.getByPath('hello').path
println tasks.getByPath(':hello').path

输出:

:hello
:hello

第二类是创建task的方法create,create方法有多种实现,你可以直接通过名字来创建一个task:

task('hello') {doLast {println "hello"}
}

也可以创建特定类型的task:

task('copy', type: Copy) {from(file('srcDir'))into(buildDir)
}

还可以创建带参数的构造函数的task:

class CustomTask extends DefaultTask {final String messagefinal int number@InjectCustomTask(String message, int number) {this.message = messagethis.number = number}
}

上面我们为CustomTask创建了一个带参数的构造函数,注意,这里需要带上@javax.inject.Inject注解,表示我们后面可以传递参数给这个构造函数。

我们可以这样使用:

tasks.create('myTask', CustomTask, 'hello', 42)

也可以这样使用:

task myTask(type: CustomTask, constructorArgs: ['hello', 42])

第三类是register,register也是用来创建新的task的,不过register执行的是延迟创建。也就是说只有当task被需要使用的时候才会被创建。

我们先看一个register方法的定义:

TaskProvider<Task> register​(String name,Action<? super Task> configurationAction)throws InvalidUserDataException

可以看到register返回了一个TaskProvider,有点像java多线程中的callable,当我们调用Provider.get()获取task值的时候,才会去创建这个task。

或者我们调用TaskCollection.getByName(java.lang.String)的时候也会创建对应的task。

最后一类是replace方法:

Task replace​(String name)
<T extends Task> T replace​(String name,Class<T> type)

replace的作用就是创建一个新的task,并且替换掉同样名字的老的task。

Task 之间的依赖

task之间的依赖关系是通过task name来决定的。我们可以在同一个项目中做task之间的依赖:

task hello {doLast {println 'Hello www.flydean.com!'}
}
task intro {dependsOn hellodoLast {println "I'm flydean"}
}

也可以跨项目进行task的依赖,如果是跨项目的task依赖的话,需要制定task的路径:

project('project-a') {task taskX {dependsOn ':project-b:taskY'doLast {println 'taskX'}}
}project('project-b') {task taskY {doLast {println 'taskY'}}
}

或者我们可以在定义好task之后,再处理task之间的依赖关系:

task taskX {doLast {println 'taskX'}
}task taskY {doLast {println 'taskY'}
}

还可以动态添加依赖关系:

task taskX {doLast {println 'taskX'}
}// Using a Groovy Closure
taskX.dependsOn {tasks.findAll { task -> task.name.startsWith('lib') }
}task lib1 {doLast {println 'lib1'}
}task lib2 {doLast {println 'lib2'}
}task notALib {doLast {println 'notALib'}
}

定义task之间的顺序

有时候我们的task之间是有执行顺序的,我们称之为对task的排序ordering。

先看一下ordering和dependency有什么区别。dependency表示的是一种强依赖关系,如果taskA依赖于taskB,那么执行taskA的时候一定要先执行taskB。

而ordering则是一种并不太强列的顺序关系。表示taskA需要在taskB之后执行,但是taskB不执行也可以。

在gradle中有两种order:分别是must run after和should run after。

taskA.mustRunAfter(taskB)表示必须遵守的顺序关系,而taskA.shouldRunAfter(taskB)则不是必须的,在下面两种情况下可以忽略这样的顺序关系:
第一种情况是如果shouldRunAfter引入了order循环的时候。

第二种情况是如果在并行执行的情况下,task所有的依赖关系都已经满足了,那么也会忽略这个顺序。

我们看下怎么使用:

task taskX {doLast {println 'flydean.com'}
}
task taskY {doLast {println 'hello'}
}
taskY.mustRunAfter taskX
//taskY.shouldRunAfter taskX

给task一些描述

我们可以给task一些描述信息,这样我们在执行gradle tasks的时候,就可以查看到:

task copy(type: Copy) {description 'Copies the resource directory to the target directory.'from 'resources'into 'target'include('**/*.txt', '**/*.xml', '**/*.properties')
}

task的条件执行

有时候我们需要根据build文件中的某些属性来判断是否执行特定的task,我们可以使用onlyIf :

task hello {doLast {println 'www.flydean.com'}
}hello.onlyIf { !project.hasProperty('skipHello') }

或者我们可以抛出StopExecutionException异常,如果遇到这个异常,那么task后面的任务将不会被执行:

task compile {doLast {println 'We are doing the compile.'}
}compile.doFirst {if (true) { throw new StopExecutionException() }
}
task myTask {dependsOn('compile')doLast {println 'I am not affected'}
}

我们还可以启动和禁用task:

myTask.enabled = false

最后我们还可以让task超时,当超时的时候,执行task的线程将会被中断,并且task将会被标记为failed。

如果我们想继续执行,那么可以使用 --continue。

注意, 只有能够响应中断的task,timeout才有用。

task hangingTask() {doLast {Thread.sleep(100000)}timeout = Duration.ofMillis(500)
}

task rule

如果我们想要给某些task定义一些规则,那么可以使用tasks.addRule:

tasks.addRule("Pattern: ping<ID>") { String taskName ->if (taskName.startsWith("ping")) {task(taskName) {doLast {println "Pinging: " + (taskName - 'ping')}}}
}

上我们定义了一个rule,如果taskName是以ping开头的话,那么将会输出对应的内容。

看下运行结果:

> gradle -q pingServer1
Pinging: Server1

我还可以将这些rules作为依赖项引入:

task groupPing {dependsOn pingServer1, pingServer2
}

Finalizer tasks

和java中的finally一样,task也可以指定对应的finalize task:

task taskX {doLast {println 'taskX'}
}
task taskY {doLast {println 'taskY'}
}taskX.finalizedBy taskY> gradle -q taskX
taskX
taskY

finalize task是一定会被执行的,即使上面的taskX中抛出了异常。

总结

以上就是gradle中task的详解,希望大家能够喜欢。

本文已收录于 http://www.flydean.com/gradle-task-in-depth/

最通俗的解读,最深刻的干货,最简洁的教程,众多你不知道的小技巧等你来发现!

欢迎关注我的公众号:「程序那些事」,懂技术,更懂你!

深入理解gradle中的task相关推荐

  1. java中什么是task_关于java:深入理解gradle中的task

    简介 在之前的文章中,咱们讲到了如何应用gradle创立一个简略的task,以及task之间怎么依赖,甚至应用了程序来创立task.在本文中,咱们会更加深刻的去理解一下gradle中的task. 定义 ...

  2. Gradle 中的Task

    项目实质上是 Task 对象的集合.一个 Task 表示一个逻辑上较为独立的执行过程,比如编译 Java 源代码,拷贝文件, 打包 Jar 文件,甚至可以是执行一个系统命令.另外,一个 Task 可以 ...

  3. 七、Gradle中的Project

    说在前面:Gradle中project是非常重要的,所以也会有非常多的API及其可配置的属性,笔者也有许多不了解的,在这只是讲一些开发中比较常用的一些API和属性.但是了解了这些,其它的自己去看,去查 ...

  4. 全面理解Gradle - 定义Task

    系列文章回顾 Gradle从入门到实战 - Groovy基础 全面理解Gradle - 执行时序 之前我们讲述了Groovy的语法,还讲述了Gradle的执行时序,本篇文章讲述下Task的定义. Ta ...

  5. C# Task 循环任务_理解C#中的ValueTask

    英文:devblogs.microsoft.com 译文:cnblogs.com/xiaoxiaotank/p/13206569.html 译者:xiaoxiaotank 前言 Task类是在.NET ...

  6. android build获取ext,android – 如何在Gradle中获取当前构建类型

    我的问题非常直接且易于理解. 题 在Gradle中,有什么办法可以在运行时获取当前的构建类型.例如,在运行assembleDebug任务时,build.gradle文件中的任务是否可以根据此任务与调试 ...

  7. 【Android 修炼手册】Gradle 篇 -- Android Gradle Plugin 主要 Task 分析

    上文回顾 上篇文章里讲了 android gradle plugin 的整体流程,引入插件以后生成了很多 Task,这篇文章就谈谈生成的这些 Task 都有什么用处,以及一些主要 Task 的实现 预 ...

  8. 深入理解gradle编译-Android进阶篇

    2019独角兽企业重金招聘Python工程师标准>>> 9/27/2016 4:23:23 PM 深入理解gradle编译-Android进阶篇 导读 本文旨在介绍Gradle构建的 ...

  9. gradle打包流程(二)--- 进一步理解gradle

    一.gradle是什么 1.gradle是一个自动化构建工具. gradle是通过组织一系列task来最终完成自动化构建的,所以task是gradle里最重要的概念.以生成一个可用的apk为例,整个过 ...

最新文章

  1. 开发安卓app游戏_游戏陪玩系统APP开发平台
  2. ubuntu配置ipv6
  3. oracle 数据不可恢复,Oracle数据恢复:错误叠加导致灾难不可恢复解决办法
  4. cout、cerr、clog
  5. Visual Studio Code的用户设置相关
  6. 项目设计基础:处理过程设计相关知识介绍​
  7. mysql用户权限表join_MyBatis映射利用mysql left join 解决N+1查询问题
  8. [HTTP] Cookie
  9. ansys toolkit教程_「实用」ANSYS电磁仿真工具推荐,做仿真的你可以试试
  10. CG100汽车编程器
  11. 数据结构之二叉树深度计算
  12. 2022-2027年中国沙漠旅游行业市场全景评估及发展战略规划报告
  13. 阻止第三方 cookie_如何在每个Web浏览器中阻止第三方Cookie
  14. 使用redis缓存来实现最近的浏览记录
  15. 英语口语 每日一句 小红书TroyChina
  16. 什么是虚拟内存?虚拟内存的原理
  17. Excel中输入整数却总是显示小数,如何调整?
  18. pytorch实现 vision_transformer
  19. 示波器的使用以及基本原理
  20. 线性可分支持向量机、线性支持向量机、非线性支持向量机的区别

热门文章

  1. 【数据结构】线性表的链式存储-单链表
  2. SPOJ3931(N个点形成三角形的最大面积)
  3. HDU4633(Polya计数)
  4. 抚摸那条船——彭晓东
  5. Catalan数推导及应用
  6. 《openssl 编程》之 RSA(转)
  7. 替换系统wsock32.dll,实现封包拦截
  8. 内核虚拟机原理|网络可编程
  9. 详解分布式一致性机制
  10. Django视图(二)