Gradle入门系列(四)——初识Gradle Task

作者 : 开心源码 本文共4580个字,预计阅读时间需要12分钟 发布时间: 2022-05-12 共200人阅读

Gradle中的Task

一、Task定义及配置

TaskContainer:管理所有的Task,如:添加、查找。

定义(创立)Task

// 直接通过task函数去创立task helloTask {  println 'i am helloTask.'}// 通过TaskContainer去创立this.tasks.create(name: 'helloTask2') {  println 'i am helloTask 2.'}

配置Task

// 给Task指定分组与形容task helloTask(group: 'study', description: 'task study'){ // 语法糖  ...}task helloTask {  group 'study' // setGroup('study')  description 'task study' // setDescription('task study')  ...}

Task除了可以配置group、description外,还可以配置name、type、dependsOn、overwrite、action。

结论:

  • 给Task分组之后,该task会被放到指定组中,方便归类查找。(默认被分组到other中)
  • 给Task增加形容,相当于给方法增加注释。

二、Task的执行介绍

Task中doFirst与doLast的使用:

task helloTask {  println 'i am helloTask.'  doFirst {    println 'the task group is: ' + group  }  // doFirst、doLast可以定义多个  doFirst {}}// 外部指定doFirst(会比在闭包内部指定的doFirst先执行)helloTask.doFirst {  println 'the task description is: ' + description}// 统计build执行时长def startBuildTime, endBuildTimethis.afterEvaluate { Project project ->  // 保证要找的task已经配置完毕  def preBuildTask = project.tasks.getByName('preBuild') // 执行build任务时,第一个被执行的Task  preBuildTask.doFirst {    startBuildTime = System.currentTimeMillis()  }  def buildTask = project.tasks.getByName('build') // 执行build任务时,最后一个被执行的Task  buildTask.doLast {    endBuildTime = System.currentTimeMillis()    println "the build time is: ${endBuildTime - startBuildTime}"  }}

结论:

  • Task闭包中直接编写的代码,会在配置阶段执行。可以通过doFirst、doLast块将代码逻辑放到执行阶段中执行。
  • doFirst、doLast可以指定多个。
  • 外部指定的doFirst、doLast会比内部指定的先执行。
  • doFirst、doLast可以对gradle中提供的已有的task进行扩展。

三、Task的执行顺序

task执行顺序指定的三种方式:

  1. dependsOn强依赖方式
  2. 通过Task输入输出指定(与第1种等效)
  3. 通过API指定执行顺序

1、Task的依赖

// ============= dependsOn强依赖方式 =============task taskX {  doLast {      println 'taskX'  }}task taskY {  doLast {      println 'taskY'  }}// 方式一:静态依赖// task taskZ(dependsOn: taskY) // 依赖一个tasktask taskZ(dependsOn: [taskX, taskY]) { // 依赖多个task,需要用数组[]表示  doLast {      println 'taskZ'  }}// 方式二:静态依赖taskZ.dependsOn(taskX, taskY)// 方式三:动态依赖task taskZ() {  dependsOn this.tasks.findAll {    // 依赖所有以lib开头的task    task -> return task.name.startsWith('lib')  }  doLast {      println 'taskZ'  }}

其余:

  • taskZ依赖了taskX与taskY,所以在执行taskZ时,会先执行taskX、taskY。
  • taskZ依赖了taskX与taskY,但taskX与taskY没有关系,它们的执行顺序是随机的。

2、Task的输入输出

inputs和outputs是Task的属性。
inputs可以是任意数据类型对象,而outputs只能是文件(或者文件夹)。
TaskA的outputs可以作为TaskB的inputs。

例子:writeTask输入扩展属性,输出文件,readTask输入writeTask的输出文件

ext {    versionCode = '1.0.0'    versionName = '100'    versionInfo = 'App的第1个版本,完成聊天功能'    destFile = file('release.xml')    if (destFile != null && !destFile.exists()) {        destFile.createNewFile()    }}task writeTask {    inputs.property('versionCode', this.versionCode)    inputs.property('versionName', this.versionName)    inputs.property('versionInfo', this.versionInfo)    outputs.file this.destFile    doLast {        def data = inputs.getProperties() // 返回一个map        File file = outputs.getFiles().getSingleFile()        // 将map转为实体对象        def versionMsg = new VersionMsg(data)        def sw = new StringWriter()        def xmlBuilder = new MarkupBuilder(sw)        if (file.text != null && file.text.size() <= 0) { // 文件中没有内容            // 实际上,xmlBuilder将xml数据写入到sw中            xmlBuilder.releases { // <releases>                release { // <releases>的子节点<release>                    versionCode(versionMsg.versionCode)                    // <release>的子节点<versionCode>1.0.0<versionCode>                    versionName(versionMsg.versionName)                    versionInfo(versionMsg.versionInfo)                }            }            // 将sw里的内容写到文件中            file.withWriter { writer ->                writer.append(sw.toString())            }        } else { // 已经有其它版本信息了            xmlBuilder.release {                versionCode(versionMsg.versionCode)                versionName(versionMsg.versionName)                versionInfo(versionMsg.versionInfo)            }            def lines = file.readLines()            def lengths = lines.size() - 1            file.withWriter { writer ->                lines.eachWithIndex { String line, int index ->                    if (index != lengths) {                        writer.append(line + '\r\n')                    } else if (index == lengths) {                        writer.append(sw.toString() + '\r\n')                        writer.append(line + '\r\n')                    }                }            }        }    }}task readTask {    inputs.file destFile    doLast {        def file = inputs.files.singleFile        println file.text    }}task taskTest(dependsOn: [writeTask, readTask]) {    doLast {        println '任务执行完毕'    }}class VersionMsg {    String versionCode    String versionName    String versionInfo}

通过执行 gradle taskTask 之后,即可以在工程目录下看到release.xml文件了。

结论:

  • 由于writeTask与readTask通过inputs、outputs产生了关联关系,所以,readTask肯定会在writeTask执行之后才执行。

3、Task API指定顺序

task指定执行顺序的api有:

  • mustRunAfter : 强行指定在某个或者某些task执行之后才执行。
  • shouldRunAfter : 与mustRunAfter一样,但不强制。
task taskX {    doLast {        println 'taskX'    }}task taskY {    // shouldRunAfter taskX    mustRunAfter taskX    doLast {        println 'taskY'    }}task taskZ {    mustRunAfter taskY    doLast {        println 'taskZ'    }}

通过执行 gradle taskY taskZ taskX 之后,可以看到终端还是按taskX、taskY、taskZ顺序执行的。

四、挂接到构建生命周期

例子:build任务执行完成后,执行一个自己设置task

this.afterEvaluate { Project project ->    def buildTask = project.tasks.getByName('build')    if (buildTask == null) throw GradleException('the build task is not found')    buildTask.doLast {        taskZ.execute()    }}

例子:Tinker将自己设置的manifestTask插入到了gradle脚本中processManifest与processResources这两个任务之间

TinkerManifestTask manifestTask = project.tasks.create("tinkerProcess${variantName}Manifest", TinkerManifestTask)...manifestTask.mustRunAfter variantOutput.processManifestvariantOutput.processResources.dependsOn manifestTask

五、Task类型

Gradle DSL Version 5.1

Copy – Gradle DSL Version 5.1

说明
1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是摆设,本站源码仅提供给会员学习使用!
7. 如遇到加密压缩包,请使用360解压,如遇到无法解压的请联系管理员
开心源码网 » Gradle入门系列(四)——初识Gradle Task

发表回复