文章目录

  • 前言
  • 创建任务
  • 任务管理
  • Action
  • 任务参数
  • 指定Type
  • 任务依赖
  • 执行顺序
  • 条件执行
  • 定义规则
  • 最终任务


前言

在Gradle 中,任务是最小执行单元,一个build.gradle是由一系列的任务组成。每个项目都由不同的任务组成。任务是构建执行的一项工作。任务可以是编译一些类,将类文件存储到单独的目标文件夹中,创建JAR,生成Javadoc或将一些归档发布到存储库。

创建任务

task是用于将任务定义到构建脚本中的关键字。

比如我们定义一个任务,然后在工具栏中就可以执行,和Maven 中的目标一样,就是一个功能。

grafana执行文件_android


一些常见创建任务的方式如下所示:

// 1. 定义一个任务
task hello {
    println 'hello world'
}
// 2. 使用参数定义任务名
task('task001') {
    println "task001"
}
// 3. 使用tasks 集合对象创建任务
tasks.create("task002") {
    println "task002"
}
// 4. 使用project获取tasks 集合对象创建任务
project.getTasks().create("task003") {
    println "task003"
}
// 5. 向tasks 集合中注册任务,被使用时才会创建
tasks.register('task004') {
    println 'task004'
}

还可以在添加任务的时候对其进行分组,比如:

task taskDev1{
    // 分组到dev
    group "dev"
    description "项目描述"
    println "method1"
}
task('taskDev2'){
    // 分组到dev
    group "dev"
    println "method2"
}

分组后,在工具栏任务列表就可以看到:

grafana执行文件_Gradle_02

任务管理

创建的任务都放在了TaskContainer 对象统一管理。

grafana执行文件_android_03


TaskContainer 常用定位任务方法如下所示:

// 1. 根据任务名查询任务,没有抛出NULL
println tasks.findByPath('task004').path
println tasks.findByPath('task005').path
// 2. 根据任务名查询任务,没有抛出UnknownTaskException
println tasks.getByPath('task004').path
println tasks.getByPath(':task005').path

Action

一个任务包含若干Action,Gradle提供了doLast()doFirst()函数,用于在执行任务时最新执行和最后执行的Action

实例如下:

task taskFirstLast{
    println "taskFirstLast"
    doLast{
        println "last"
    }
    doFirst{
        println "first"
    }
    group "dev"
}

也可以使用如下方式编写:

task taskFirstLast {
    println "taskFirstLast"
}
myTask.doFirst {
    println "first"
}
myTask.doLast {
    println "last"
}

任务参数

定义Task的时候是可以指定很多参数的,如下所示:

参数

含义

默认值

name

task的名字

不能为空,必须指定

type

task的“父类”

DefaultTask

overwrite

是否替换已经存在的task

false

dependsOn

task依赖的task的集合 []

group

task属于哪个组

null

description

task的描述

null

可以通过以下两种方式定义有参数的任务:

task task001{
}
task task002{
}
// 1. 定义有参任务方式1
project.task('task006', group: "dev", description: "有参任务", dependsOn: ["task001", "task002"] ) {
    println "task006"
}
// 2. 定义有参任务方式2
task task007 {
    group "dev"
    description "有参任务"
    dependsOn task001, task002
    doLast {
        println "task007"
    }
}

指定Type

创建任务的时候可以通过type: SomeType 指定Type,Type其实就是告诉Gradle,这个新建的Task对象会从哪个基类Task派生。

Gradle本身提供了一些通用的Task,最常见的有Copy 任务,还提供了其他如DeleteSync等。

下面示例中是一个简单的Copy 任务:

// 创建任务,派生自Copy, 可以实现复制文件
task copyDocs(type: Copy) {
    from 'src/main/doc' // 被复制的文件
    into 'build/target/doc' // 目标
}

Copy 的时候还可以进行重命名:

task chVer(type: Copy) {
    from "src/main/manifest/AndroidManifestCopy.xml"  // 复制src/main/manifest/目录下的AndroidManifest.xml
    into 'src/main'  // 复制到指定目标目录
    rename { String fileName -> //在复制时重命名文件
        fileName = "AndroidManifest.xml" // 重命名
    }
}

Copy 还可以配置复制规则闭包、过滤、重命名等:

// 这是个Ant filter
import org.apache.tools.ant.filters.ReplaceTokens
// 创建一个复制规则闭包
def copyRule = copySpec {
    from 'src/data'
    include '*.data'
}
task initConfig(type: Copy) {
    from('src/main/config') {
        include '**/*.properties'
        include '**/*.xml'
        filter(ReplaceTokens, tokens: [version: '2.3.1']) // 过滤
    }
    from('src/main/config') {
        exclude '**/*.properties', '**/*.xml'
    }
    from('src/main/languages') {
        rename 'EN_US_(.*)', '$1' // 重命名
    }
    into 'build/target/config'
    exclude '**/*.bak' // 排查文件
    includeEmptyDirs = false // 是否包含空文件夹
    with copyRule // 引用规则
}

其他的一些任务类型如下所示:

任务

描述

Copy

将文件复制到目标目录

Delete

删除文件和目录

Exec

执行命令行程序

GradleBuild

执行Gradle构建

JavaExec

在一个子进程中执行一个Java程序

Sync

同步源文件文件或者目录

Upload

将源文件配置的组件上传到执行的仓库

还可以通过继承DefaultTask类自定义类型,如下所示:

class TestTask extends DefaultTask {
     // 定义输入参数,任务没有传入或者设置参数,将使用默认参数
    @Input
    String message = 'TestTask'
    // 定义执行方法
    @TaskAction
    def hello(){
        println "Hello:$message"
    }
}
// 注册任务,没有传入参数
tasks.register('myTask', TestTask)

// 注册任务,并定义参数值
task hi(type:TestTask){
    message ="Hi"
}

任务依赖

任务之间也具有依赖性,通过dependsOn 指定任务名称,就表示依赖其他任务。

同一个工程中建立依赖关系如下所示,执行时,会先执行依赖中的任务,在执行当前任务。

task depends001 {
     println 'depends001'
}
task depends002 {
    dependsOn depends001
    println 'depends002'
}

如果依赖其他项目的任务,按照如下写法:

project('project-a') {
    task taskX {
        dependsOn ':project-b:taskY' // 依赖其他项目的任务
        doLast { println 'taskX' }
    }
}

执行顺序

任务是可以进行排序的,通过这种方式可以在某些情况下控制任务的执行顺序,而不是通过强制依赖的方式。这个功能是非常有用的,比如项目中设置的顺序是必须先执行单元测试,然后才能进行集成测试来保证软件的质量,测速完成后再打包上传发布等操作。

Gradle中有两种排序方式:

  • mustRunAfter:必须在某个任务之后执行
  • shouldRunAfter :应该在某个任务之后执行

如下所示,不过好像执行必须写在doFirst或者doLast中才有效。

task order001 {
    doFirst{
        println "<< order001 doFirst 的打印"
    }
}
task order002 {
    doFirst{
        println "<< order002 doFirst 的打印"
    }
}
order001.mustRunAfter order002
//order001.shouldRunAfter order002

条件执行

可以给任务加上条件判断决定是否执行该任务,onlyIf 表达式为真时,任务才会执行。

task test009 {
    doLast { println '=======test009' }
}
// onlyIf 中的表达式为真,才执行任务
test009.onlyIf { !project.hasProperty('avab') }

可以直接设置是否开启任务:

// 是否开启任务,false 表示不开启任务
test009.enabled = false

还可以抛出StopExecutionException异常,如果遇到这个异常,那么该任务将不会被执行:

task test010 {
    doLast { println 'test010' }
}
test010.doFirst {
    // 条件判断,抛出异常,该任务后续则不执行
    throw new StopExecutionException()
}
task test011 {
    dependsOn('test010')
    doLast {
        println 'test011'
    }
}

定义规则

tasks.addRule可以定义一些规则:

当执行、依赖一个不存在的任务时,Gradle 会执行失败,提示信息是任务不存在。可以使用规则对其进行修改,让其在执行、依赖不存在的任务时,不会执行失败,而是打印提示信息。代码如下所示:

tasks.addRule("对该规则的一个,便于调试等"){ String taskName ->
    task(taskName){
        doLast{
            println "该 ${taskName} 任务不存在,请查证后再执行"
        }
    }
}
task taskRule{
    dependsOn missTask
}

最终任务

和java中的finally一样,task也可以指定对应的最终必须执行的任务,即使上面的任务中抛出了异常。

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