原文发于微信公众号 jzman-blog,欢送关注交换。
后面几篇学习了 Gradle 构建工作的基础知识,理解了 Project 和 Task 这两个概念,倡议先浏览后面几篇文章:
- Gradle系列之初识Gradle
- Gradle之Groovy根底篇
- Gradle系列之构建脚本根底
Gradle 的构建工作是有一系列的 Task 来实现的,本文将针对 Task 进行具体介绍,本文次要内容如下:
- 多种形式创立工作
- 多种形式拜访工作
- 工作分组和形容
- 操作符
- 工作的执行剖析
- 工作排序
- 工作的启用和禁用
- 工作的onlyIf断言
- 工作规定
多种形式创立工作
Gradle 中能够应用多种形式来创立工作,多种创立工作的形式最终反映在 Project 提供的快捷办法以及内置的 TaskContainer 提供的 create 办法,上面是几种常见的创立工作的形式:
/** * 第一种创立工作形式: * 办法原型:Task task(String name) throws InvalidUserDataException; *///定义Task变量接管task()办法创立的Task,办法配置创立的Taskdef Task taskA = task(taskA)//配置创立的TasktaskA.doFirst { println "第一种创立工作的形式"}/**task * 第二种创立工作形式:可在Map参数中进行相干配置,如依赖、工作形容、组别等 * 办法原型:Task task(Map<String, ?> args, String name) throws InvalidUserDataException; */def Task taskB = task(group: BasePlugin.BUILD_GROUP,taskB,description: "形容")//配置创立的TasktaskB.doLast { println "第二种创立工作的形式" println "工作taskB分组:${taskB.group}" println "工作taskB形容:${taskB.description}"}/** * 第三种创立工作形式:通过闭包的形式创立Task,闭包里的委托对象就是Task,即可在闭包内调用Task * 的所有属性和办法来进行Task的配置 * 办法原型:Task task(String name, Closure configureClosure); */task taskC{ description 'taskC的形容' group BasePlugin.BUILD_GROUP doFirst{ println "第三种创立工作的形式" println "工作taskC分组:${group}" println "工作taskC形容:${description}" }}/** * 第四种创立工作的形式:可在闭包中灵便配置,也可在Map参数中配置,闭包中中的配置父笼罩Map中雷同的配置 * 办法原型:Task task(Map<String, ?> args, String name, Closure configureClosure); */def Task taskD = task(group: BasePlugin.BUILD_GROUP,taskD,description: "形容"){ description 'taskD的形容' group BasePlugin.UPLOAD_GROUP doFirst{ println "第四种创立工作的形式" println "工作taskD分组:${group}" println "工作taskD形容:${description}" }}
下面是创立工作的四种形式,应用时抉择适合的创立形式即可,下面提到 Map 中能够配置 Task 的相干参数,上面是是 Map 中可应用的配置:
type:基于一个已存在的Task来创立,相似于类的继承,默认值DefaultTaskoverwrite:是否替换存在的Task,个别和type配合应用,默认值falsedependsOn:配置当前任务的依赖,默认值[]action:增加到工作中的一个Action或者是一个闭包,默认值为nulldescription:工作形容,默认值nullgroup:工作分组,默认值null
通过闭包的形式创立 Task,闭包里的委托对象就是 Task,即可在闭包内调用 Task
的所有属性和办法来进行 Task 的配置,能够说应用闭包的这种工作创立形式更灵便,此外还能够应用 TaskContainer 创立工作,参考如下:
//应用TaskContainer创立工作的形式tasks.create("taskE"){ description 'taskE的形容' group BasePlugin.BUILD_GROUP doFirst{ println "第三种创立工作的形式" println "工作taskE分组:${group}" println "工作taskE形容:${description}" }}
tasks 是 Project 的属性,其类型是 TaskContainer,所以能够通过 tasks 来创立工作,当然 TaskContainer 创立工作也有创立工作的其余构造方法,到此对于工作的创立就根本介绍完了。
多种形式拜访工作
创立的工作(Task)属于我的项目(Project)的一个属性,其属性名就是工作名,该属性的类型是 Task,如果已知工作名称,那么能够通过工作名间接拜访和操纵该工作了,也能够了解拜访和操纵该工作所对应的 Task 对象,参考
如下:
/** * 拜访工作的第一种形式:Task名称.doLast{} */task taskF{}taskF.doLast{ println "第一种拜访工作的形式"}
工作都是通过 TaskContainer 的 create 办法创立的,而 TaskContainer 是创立工作的汇合,在 Project 中可通过 tasks 属性拜访 TaskContainer ,tasks 的类型就是 TaskContainer,所以对于曾经创立的工作可通过拜访几何元素的形式拜访已创立工作的属性和办法,参考代码如下:
/** * 拜访工作的第二种形式:应用TaskContainer拜访工作 */task taskG{}tasks['taskG'].doLast { println "第二种拜访工作的形式"}
在 Groovy 中 [] 也是一个操作符,下面 tasks['taskG'] 的真正含意是 tasks.getAt('taskG') , getAt() 办法在 TaskCollection 中的办法,这样能够通过工作名称对相干工作进行拜访和操作。
还能够通过门路拜访的形式拜访工作,通过门路拜访工作有两个要害办法:findByPath 和 getByPath,区别在于前者找不到指定工作的时候会返回 null,后者找不到工作的时候会抛出 UnknowTaskException 异样,代码参考如下:
/** * 拜访工作的第三种形式:应用门路拜访工作 */task taskH{ println 'taskH' //通过门路拜访工作,参数能够是门路(没有拜访胜利,写法如下) println tasks.findByPath(':GradleTask:taskG') //通过门路拜访工作,参数能够是工作名称 println tasks.findByPath('taskG') println tasks.getByPath('taskG')}
上述代码执行后果参考如下:
PS E:\Gradle\study\GradleTask> gradle taskH> Configure project :taskHnulltask ':taskG'task ':taskG'FAILURE: Build failed with an exception.* Where:Build file 'E:\Gradle\study\GradleTask\build.gradle' line: 98* What went wrong:A problem occurred evaluating root project 'GradleTask'.> Task with path 'test' not found in root project 'GradleTask'.* Try:Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.* Get more help at https://help.gradle.orgBUILD FAILED in 2s
应用门路拜访工作的过程,参数写成门路拜访不到具体的工作,可能是写法问题,心愿在前面的学习中可能解决。
此外,还能够通过工作名称拜访,办法次要是 findByName 和 getByName,区别和第三种拜访形式一样, 代码参考如下:
/** * 拜访工作的第四种形式:应用工作名称拜访 */task taskJtasks['taskJ'].doLast{ println 'taskJ' println tasks.findByName('taskJ') println tasks.getByName('taskJ')}
下面学习了拜访工作的四种形式,通过对 Gradle 拜访工作的理解,在具体的我的项目构建上在联合下面拜访工作的形式灵便应用。
工作分组和形容
对于工作分组及形容实际上在之前的文章曾经提到过且配置过,这里再简略阐明一下,工作分组和形容实际上就是对曾经创立的工作配置分组和工作形容,如上面这样配置:
//工作分组与形容def Task task1 = task taskKtask1.group = BasePlugin.BUILD_GROUPtask1.description = '测试工作分组与形容'task1.doLast { println "taskK is group = ${group}, description = ${description}"}
上面是上述代码执行后果,参考如下:
PS E:\Gradle\study\GradleTask> gradle taskK> Task :taskKtaskK is group = build, description = 测试工作分组与形容BUILD SUCCESSFUL in 2s1 actionable task: 1 executed
从执行后果能够看出,如果配置了工作的相干属性,那么就能够拜访到工作的所有信息了。
操作符
学习一个操作符 << ,之前的测试代码中为了测试都会调用 task.doLast() 办法,咱们能够应用 << 操作符来代替 doLast 办法,也就是说 daLast() 办法能够这样写:
//<< 工作操作符//简写形式,Gradle 5.0 开始以不举荐这种写法task taskL <<{ println "doLast"}//举荐写法task taskL{ doLast{ println "doLast" }}
上述两种写法的执行后果参考如下:
PS E:\Gradle\study\GradleTask> gradle taskL> Configure project :The Task.leftShift(Closure) method has been deprecated and is scheduled to be removed in Gradle 5.0. Please use Task.doLast(Action) instead. at build_6syzx8ks0l09hby4j6yn247u9.run(E:\Gradle\study\GradleTask\build.gradle:123)> Task :taskLdoLastBUILD SUCCESSFUL in 2s1 actionable task: 1 executedPS E:\Gradle\study\GradleTask> gradle taskL> Task :taskLdoLastBUILD SUCCESSFUL in 2s1 actionable task: 1 executedPS E:\Gradle\study\GradleTask>
从输入后果能够看到两种写法都输入了想要的后果,同时察看日志发现这种简写形式曾经在 Gradle 5.0 开始曾经被放弃,所以举荐搭建应用 doLast 的形式配置工作。
工作的执行剖析
在 Gradle 工作执行过程中,咱们能够通过 doFirst 和 doLast 在工作执行之前或执行之后进行工作相干配置,当咱们执行一个工作的时候,实际上是在执行该 Task 所领有的 action,能够通过 getActions() 办法获取所有能够执行的 action,上面自定义一个 Task 类型 CustomTask ,并应用注解 @TaskAction 标注办法 doSelf 示意 Task 自身要执行的办法,代码如下:
//工作执行流程剖析def Task taskA = task taskB(type: CustomTask)taskA.doFirst { println "Task执行之前调用:doFirst"}taskA.doLast { println "Task执行之后调用:doLast"}class CustomTask extends DefaultTask{ @TaskAction def doSelf(){ println "Task执行自身调用:doSelf" }}
上述代码的执行后果如下:
PS E:\Gradle\study\GradleTask2> gradle taskB> Task :taskBTask执行之前调用:doFirstTask执行自身调用:doSelfTask执行之后调用:doLastBUILD SUCCESSFUL in 2s1 actionable task: 1 executed
因为 Task 的执行是在遍历须要执行的 action 列表,为了保障执行的程序,则必须将 doFirst 对应的 action 放在 action 列表的最后面,doLast 对应的 action 放在 action 列表的最初面,doSelf 对应的 action 搁置在列表的两头地位,这样就能保障对应的执行程序了,上面是伪代码:
//创立工作的时候将应用@TaskAction标注的办法作为Task自身执行的Task//此时,工作正在创立,actionList外面只有Task自身执行的ActionactionList.add(0,doSelfAction)//工作创立实现之后,如果设置了doFirst则会在actionList最后面增加doFist对应的action//此时,doFirst对应的action增加actionList的最后面,保障了doFirst办法在工作开始执行之前执行actionList.add(0,doFirstAction)//工作创立实现之后,如果设置了doLast则会在actionList最初面增加doLast对应的action,保障了doLast办法在工作开始执行之后执行actionList.add(doLastAction)
工作执行的流程根本如上,尽量在具体实际中多领会。
工作排序
Gradle 中工作排序应用到的是 Task 的两个办法 shoundRunAfter 和 mustRunAfter,能够不便的管制两个工作谁先执行:
/** * 工作程序 * taskC.shouldRunAfter(taskD):示意taskC要在taskD的前面执行 * taskC.mustRunAfter(taskD):示意taskC必须要在taskD的前面执行 */task taskC { doFirst{ println "taskC" }}task taskD { doFirst{ println "taskD" }}taskC.shouldRunAfter(taskD)
上述代码的执行后果,参考如下:
PS E:\Gradle\study\GradleTask2> gradle taskC taskD> Task :taskDtaskD> Task :taskCtaskCBUILD SUCCESSFUL in 2s2 actionable tasks: 2 executed
工作的启用和禁用
Task 中有个 enabled 属性,能够应用该属性启用和禁用某个工作,设置为 true 则启用该工作,反之则禁用该工作,该属性默认为 true,应用如下所示:
taskA.enabled = true
工作的onlyIf断言
断言是一个条件表达式, Task 对象有一个 onlyIf 办法,该办法能够接管一个闭包作为参数,如果该闭包内参数返回 true,则该工作执行,反之则不执行该工作,这样能够通过工作的断言来管制那些工作须要执行,上面通过一个打包的案列来学习工作的断言,代码参考如下:
//工作的onlyIf断言final String BUILD_ALL = 'all'final String BUILD_FIRST = 'first'final String BUILD_OTHERS = 'others'task taskTencentRelease{ doLast{ println "打利用宝渠道包" }}task taskBaiduRelease{ doLast{ println "打百度手机助手渠道包" }}task taskMiuiRelease{ doLast{ println "打小米利用商店渠道包" }}task buildTask{ group BasePlugin.BUILD_GROUP description "打渠道包"}//为buildTask增加依赖的具体任务buildTask.dependsOn taskTencentRelease, taskBaiduRelease, taskMiuiReleasetaskTencentRelease.onlyIf{ if (project.hasProperty("buildApp")){ Object buildApp = project.property("buildApp") return BUILD_ALL == buildApp || BUILD_FIRST == buildApp }else{ return true }}taskBaiduRelease.onlyIf{ if (project.hasProperty("buildApp")){ Object buildApp = project.property("buildApp") return BUILD_ALL == buildApp || BUILD_FIRST == buildApp }else{ return true }}taskMiuiRelease.onlyIf{ if (project.hasProperty("buildApp")){ Object buildApp = project.property("buildApp") return BUILD_OTHERS == buildApp || BUILD_ALL == buildApp }else{ return true }}
上面是上述代码的执行后果:
PS E:\Gradle\study\GradleTask2> gradle -PbuildApp=first buildTask> Task :taskBaiduRelease打百度手机助手渠道包> Task :taskTencentRelease打利用宝渠道包BUILD SUCCESSFUL in 1s2 actionable tasks: 2 executedPS E:\Gradle\study\GradleTask2> gradle -PbuildApp=others buildTask> Task :taskMiuiRelease打小米利用商店渠道包BUILD SUCCESSFUL in 1s1 actionable task: 1 executedPS E:\Gradle\study\GradleTask2> gradle -PbuildApp=all buildTask> Task :taskBaiduRelease打百度手机助手渠道包> Task :taskMiuiRelease打小米利用商店渠道包> Task :taskTencentRelease打利用宝渠道包BUILD SUCCESSFUL in 1s3 actionable tasks: 3 executed
能够看出,当咱们执行 buildTask 时为 Project 配置了属性 buildApp,通过 buildApp 不同的值,借助 onlyIf 实现了不同渠道包的定制打包策略,可在理论开发中借鉴加以应用。
此外,留神上述代码执行命令的写法,具体如下:
//其中buildApp和=前面的值others是键值对的关系,应用命令执行工作时可应用-P命令简写//-P要为以后Project指定K-V的属性键值对,即-PK=Vgradle -PbuildApp=others buildTask
工作规定
创立的工作都是在 TaskContain 外面,我么能够通过从 Project 的属性 tasks 中依据工作的名称来获取想要获取的工作,能够通过 TaskContain 的 addRule 办法增加相应的工作规定,参考代码如下:
//工作规定tasks.addRule("对该规定的一个形容"){ //在闭包中经常将->作为参数与代码块之间的分隔符 String taskName -> task(taskName) { doLast{ println "${taskName} 不存在" } }}task taskTest{ dependsOn taskX}
上述代码的执行后果:
PS E:\Gradle\study\GradleTask2> gradle taskTest> Task :taskXtaskX 不存在BUILD SUCCESSFUL in 1s1 actionable task: 1 executed
如果不指定对某些非凡状况的工作解决,则会报错,如果解决了则会输入相干的提示信息,Gradle 工作的理解和学习就到此为止。能够关注公众号:躬行之(jzman-blog),一起交流学习。