Gradle系列之熟悉Gradle义务

admin 2个月前 (08-08) 科技 93 1

原文发于微信民众号 jzman-blog,迎接关注交流。

前面几篇学习了 Gradle 构建义务的基础知识,领会了 Project 和 Task 这两个观点,建议先阅读前面几篇文章:

  • Gradle系列之初识Gradle
  • Gradle之Groovy基础篇
  • Gradle系列之构建剧本基础

Gradle 的构建事情是有一系列的 Task 来完成的,本文将针对 Task 举行详细先容,本文主要内容如下:

  1. 多种方式建立义务
  2. 多种方式接见义务
  3. 义务分组和形貌
  4. 操作符
  5. 义务的执行剖析
  6. 义务排序
  7. 义务的启用和禁用
  8. 义务的onlyIf断言
  9. 义务规则

多种方式建立义务

Gradle 中可以使用多种方式来建立义务,多种建立义务的方式最终反映在 Project 提供的快捷方式以及内置的 TaskContainer 提供的 create 方式,下面是几种常见的建立义务的方式:

/**
 * 第一种建立义务方式:
 * 方式原型:Task task(String name) throws InvalidUserDataException;
 */
//界说Task变量吸收task()方式建立的Task,方式设置建立的Task
def Task taskA = task(taskA)
//设置建立的Task
taskA.doFirst {
    println "第一种建立义务的方式"
}

/**task
 * 第二种建立义务方式:可在Map参数中举行相关设置,如依赖、义务形貌、组别等
 * 方式原型:Task task(Map<String, ?> args, String name) throws InvalidUserDataException;
 */
def Task taskB = task(group: BasePlugin.BUILD_GROUP,taskB,description: "形貌")
//设置建立的Task
taskB.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来建立,类似于类的继续,默认值DefaultTask
overwrite:是否替换存在的Task,一样平常和type配合使用,默认值false
dependsOn:设置当前义务的依赖,默认值[]
action:添加到义务中的一个Action或者是一个闭包,默认值为null
description:义务形貌,默认值null
group:义务分组,默认值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 :
taskH
null
task ':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.org

BUILD FAILED in 2s

使用路径接见义务的历程,参数写成路径接见不到详细的义务,可能是写法问题,希望在后面的学习中能够解决。

此外,还可以通过义务名称接见,方式主要是 findByName 和 getByName,区别和第三种接见方式一样, 代码参考如下:

/**
 * 接见义务的第四种方式:使用义务名称接见
 */
task taskJ
tasks['taskJ'].doLast{
    println 'taskJ'
    println tasks.findByName('taskJ')
    println tasks.getByName('taskJ')
}

上面学习了接见义务的四种方式,通过对 Gradle 接见义务的领会,在详细的项目构建上在连系上面接见义务的方式天真使用。

义务分组和形貌

对于义务分组及形貌现实上在之前的文章已经提到过且设置过,这里再简朴说明一下,义务分组和形貌现实上就是对已经建立的义务设置分组和义务形貌,如下面这样设置:

//义务分组与形貌
def Task task1 = task taskK
task1.group = BasePlugin.BUILD_GROUP
task1.description = '测试义务分组与形貌'
task1.doLast {
    println "taskK is group = ${group}, description = ${description}"
}

下面是上述代码执行效果,参考如下:

PS E:\Gradle\study\GradleTask> gradle taskK

> Task :taskK
taskK is group = build, description = 测试义务分组与形貌


BUILD SUCCESSFUL in 2s
1 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 :taskL
doLast


BUILD SUCCESSFUL in 2s
1 actionable task: 1 executed
PS E:\Gradle\study\GradleTask> gradle taskL

> Task :taskL
doLast


BUILD SUCCESSFUL in 2s
1 actionable task: 1 executed
PS 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 :taskB
Task执行之前挪用:doFirst
Task执行自己挪用:doSelf
Task执行之后挪用:doLast


BUILD SUCCESSFUL in 2s
1 actionable task: 1 executed

由于 Task 的执行是在遍历需要执行的 action 列表,为了保证执行的顺序,则必须将 doFirst 对应的 action 放在 action 列表的最前面,doLast 对应的 action 放在 action 列表的最后面,doSelf 对应的 action 放置在列表的中心位置,这样就能保证对应的执行顺序了,下面是伪代码:

//建立义务的时刻将使用@TaskAction标注的方式作为Task自己执行的Task
//此时,义务正在建立,actionList内里只有Task自己执行的Action
actionList.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 :taskD
taskD

> Task :taskC
taskC


BUILD SUCCESSFUL in 2s
2 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, taskMiuiRelease

taskTencentRelease.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 1s
2 actionable tasks: 2 executed
PS E:\Gradle\study\GradleTask2> gradle -PbuildApp=others buildTask

> Task :taskMiuiRelease
打小米应用商铺渠道包


BUILD SUCCESSFUL in 1s
1 actionable task: 1 executed
PS E:\Gradle\study\GradleTask2> gradle -PbuildApp=all buildTask

> Task :taskBaiduRelease
打百度手机助手渠道包

> Task :taskMiuiRelease
打小米应用商铺渠道包

> Task :taskTencentRelease
打应用宝渠道包


BUILD SUCCESSFUL in 1s
3 actionable tasks: 3 executed

可以看出,当我们执行 buildTask 时为 Project 设置了属性 buildApp,通过 buildApp 差别的值,借助 onlyIf 实现了差别渠道包的定制打包计谋,可在现实开发中借鉴加以使用。

此外,注重上述代码执行下令的写法,详细如下:

//其中buildApp和=后面的值others是键值对的关系,使用下令执行义务时可使用-P下令简写
//-P要为当前Project指定K-V的属性键值对,即-PK=V
gradle -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 :taskX
taskX 不存在


BUILD SUCCESSFUL in 1s
1 actionable task: 1 executed

若是不指定对某些特殊情况的义务处置,则会报错,若是处置了则会输出相关的提醒信息,Gradle 义务的领会和学习就到此为止。可以关注民众号:零点小筑(jzman-blog),一起交流学习。

,

联博以太坊高度

www.326681.com采用以太坊区块链高度哈希值作为统计数据,联博以太坊统计数据开源、公平、无任何作弊可能性。联博统计免费提供API接口,支持多语言接入。

申博声明:该文看法仅代表作者自己,与本平台无关。转载请注明:Gradle系列之熟悉Gradle义务

网友评论

  • (*)

最新评论

  • UG环球网址 2020-08-08 00:12:24 回复

    联博API接口www.326681.com采用以太坊区块链高度哈希值作为统计数据,联博以太坊统计数据开源、公平、无任何作弊可能性。联博统计免费提供API接口,支持多语言接入。我不淡定了

    1