全面理解Gradle - 定义Task

系列文章回顾
Gradle从入门到实战 - Groovy基础
全面理解Gradle - 执行时序html

以前咱们讲述了Groovy的语法,还讲述了Gradle的执行时序,本篇文章讲述下Task的定义。java

Task能够理解为Gradle的执行单元,实在是过重要了。根据前面的分析,Gradle经过一个个task来完成具体的构建任务,下面咱们来看下Task的定义。android

最简单直接,经过以下方式来定义:web

task myTask {
    println "config myTask"
}

咱们执行下api

renyugang$ gradle myTask

config myTask

再执行下ruby

renyugang$ gradle clean

config myTask

能够看出,经过上述方式定义的task,括号内部的代码会在配置阶段执行,也就是说,只要我执行任何一个task,那段代码都会执行,由于每一个task执行以前都须要进行一遍完整的配置。app

可是不少时候咱们并不须要写配置代码,咱们想要括号内的代码仅仅在执行咱们的task的时候才执行,这个时候能够经过doFirst或者doLast来完成。svg

  • doFirst:task执行时,最开始的操做
  • doLast:task执行时,最后的操做
// 定义并配置myTask
task myTask {
    println "config myTask"
}

myTask.doLast {
    println "after execute myTask"
}

myTask.doFirst {
    println "before execute myTask"
}

执行结果以下学习

config myTask
:app:myTask
before execute myTask
after execute myTask

除此以外,doLast还有一个等价的操做leftShift,leftShift还能够缩写为<<,所以下面的三种实现效果等价:gradle

myTask.doLast {
    println "after execute myTask"
}

myTask.leftShift {
    println "after execute myTask"
}

myTask << {
    println "after execute myTask"
}

在上面的demo中,myTask真正执行的时候啥都没干,它只是在执行的最开始和最后作了一些事情。

其实,经过@TaskAction操做符也能够指定一个Task执行时要作的事情,它区别于doFirst和doLast,不过@TaskAction平时用的较少,这里简单示范下:

class RygTask extends DefaultTask {

    String message = 'This is RygTask'

    // @TaskAction 表示该Task要执行的动做,即在调用该Task时,hello()方法将被执行
    @TaskAction
    def hello(){
        println "Hello world. $message"
    }
}

// hello使用了默认的message值
task hello(type:RygTask)

// 从新设置了message的值
task hello1(type:RygTask){
    message ="I am an android developer"
}

执行gradle hello hello1

:app:hello
Hello world. This is RygTask

:app:hello1
Hello world. I am an android developer

除了上面的Task定义方式之外,Gradle自己还提供了一些已有的Task供咱们使用,好比Copy、Delete、Sync等。所以咱们定义Task的时候是能够继承已有的Task,好比咱们能够继承自系统的Copy Task来完成文件的拷贝操做。

task myTask(type: Copy) { configure closure }

除了这种方式之外,咱们还能够经过API来动态建立Task,API也有不少,这里介绍几个最经常使用的(Gradle水很深,API特别灵活,你们记住最经常使用的就好)。

// 下面三种定义也如出一辙

task myTask << {
    println "after execute myTask"
}

project.task('myTask').doLast {
    println "after execute myTask"
}

project.tasks.create('myTask').doLast {
    println "after execute myTask"
}

定义Task的时候是能够指定不少参数的,以下所示:

参数 含义 默认值
name task的名字 不能为空,必须指定
type task的“父类” DefaultTask
overwrite 是否替换已经存在的task false
dependsOn task依赖的task的集合 []
group task属于哪一个组 null
description task的描述 null

在上面的例子中都没涉及参数,下面举个带参数的栗子。

task myTask1 << {
    println "execute myTask1"
}

task myTask2 << {
    println "execute myTask2"
}

// 定义一个名字为rygTask的task,属于renyugang分组,而且依赖myTask1和myTask2两个task。
project.task('rygTask', group: "renyugang", description: "我本身的Task", dependsOn: ["myTask1", "myTask2"] ).doLast {
    println "execute rygTask"
}

经过Gradle tasks来查看:

Publishing tasks ----------------
bintrayUpload - Publishes artifacts to bintray.com.

Renyugang tasks ---------------
rygTask - 我本身的Task

Upload tasks ------------
uploadArchives - Uploads all artifacts belonging to configuration ':AndroidStub:archives'

尝试执行gradle rygTask,结果以下:

:app:myTask1
execute myTask1

:app:myTask2
execute myTask2

:app:rygTask
execute rygTask

结果不用我解释了,相信你们都能看懂。

补充说明

  • Gradle命令是支持连在一块儿拼写的,好比gradle hello hello1,那么gradle将会先执行hello,而后再执行hello1。
  • Gradle命令是能够缩写的,前提是这个缩写可以惟一地限定一个task。好比rygTask,那么执行的时候就能够缩写为gradle rTask

最后,定义task的API不少,我介绍了最经常使用的部分,剩下的细节仍是须要你们查看Gradle文档,其实学习Gradle就是一个查文档的过程。以下几个文档,你们读读。

Project API
TaskContainer API
Task API