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执行顺序指定的三种方式:
dependsOn强依赖方式
通过Task输入输出指定(与第1种等效)
通过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.processManifest variantOutput.processResources.dependsOn manifestTask
作者:GitLqr
链接:https://www.jianshu.com/p/177ec58493bb
共同学习,写下你的评论
评论加载中...
作者其他优质文章