Gradle Task Configuration Avoidance

news/2024/5/20 4:03:24 标签: Gradle

这个章节介绍了处理任务时"避免配置",并且解释了迁移构建以有效实用配置避免api的一些指导原则,这里描述的API与现有的API共存,但是现有的API将在以后的几个重要版本中被代替。在Gradle 5.1中,我们建议使用配置避免的API来创建自定义的Plugins。

配置避免API是如何工作的?

nutshell中,该API允许构建避免在Gradle的配置阶段创建和配置任务的成本,而这些任务永远不会被执行。例如,当跑一个编译的任务,其他像代码质量,测试和发版的不相关的任务将不会被执行,所以任何花费在创建和配置上的任务都是不必要的。配置避免API避免配置任务,如果这些任务在在构建过程中是不被需要的,这些任务会对整个构建时间产生巨大的影响。

为了避免创建和配置任务,我们使用"被注册的"而不是被创建的。当一个任务在这种状态下,这个任务时被标记为可以构建和配置的,并且引用可以通过这个任务,但是这个任务本身并不会真正的被创建,并且配置项目不会被执行。这个任务将一直保持这种状态直到在编译过程中需要实例化这个任务对象。如果这个任务永远不被需要,任务将一直保持注册的状态,那么这个任务的创建和配置的时间将被节省。

Gradle中,你可以用TaskContainer.register(java.lang.String)来注册任务。此方法有多种变体,允许提供用于修改任务配置的任务类型和/或操作。方法register(...)返回的是一个TaskProvider,而不是一个Task类型,TaskProvider类型可以用在所有Task可以用的地方。

指导

如何延迟一个任务的创建

有效的配置避免任务要求构建者将TaskContainer.create(java.lang.String)变为TaskContainer.register(java.lang.String)。老版本的Gradle仅支持create(...)接口请求,应该避免使用这个API。单独使用register(...)可能不能完全避免任务配置。可能需要改变其他的代码,以下是解释。

如何延迟任务配置

DomainObjectCollection.all(org.gradle.api.Action)DomainObjectCollection.withType(java.lang.Class,org.gradle.api.Action)将立即创建和配置任何注册过的任务。为了延迟任务配置,你需要迁移配置API,可以看最后的表格。

如何引用一个没有创建/配置的任务

可以通过TaskContainer.register(java.lang.String)或者使用TaskCollection.named(java.lang.String)这两个方法来获取。
使用Provider.get()或者TaskCollection.getByName(java.lang.String)会创建或者配置该task。函数像Task.dependsOn(java.lang.Object...)ConfigurableFileCollection.builtBy(java.lang.Object...)与任务的工作机制是一样的。
如果你想使用名称来配置一个任务,你将需要使用等效的配置避免。可以看最下面的表格。

如何获取任务的实例?

如果你热灸想获取任务的实例,你需要使用TaskCollection.named(java.lang.String)Provicer.get()。使用这两个方法,将会触发创建和配置任务流程。

迁移指导

接下来将介绍一些我们在迁移过程中需要遵循的一般准则,和一些建议。我们还将介绍一些故障排除和陷阱,以帮助您解决迁移过程中可能遇到的一些问题。

普遍准则

  1. 使用help任务作为一个基准在迁移的过程中。help任务时一个完美的候选基准对于你的迁移过程。
  2. 仅在配置操作中更改当前任务。因为任务配置操作现在可以立即、稍后或从不运行,所以修改当前任务之外的任何内容都可能导致构建中出现不确定的行为。考虑以下代码:
val check by tasks.registering
tasks.register("verificationTask") {
    // Configure verificationTask

    // Run verificationTask when someone runs check
    check.get().dependsOn(this)
}

执行gradle检查任务应该执行verificationTask,但是在这个例子中,它不会执行。这是因为verificationTaskcheck之间的依赖关系只在verificationTask实现时才会发生。为了避免此类问题,您必须只修改与配置操作关联的任务。其他任务应该在它们自己的配置操作中进行修改。代码将变成:

val check by tasks.registering
val verificationTask by tasks.registering {
    // Configure verificationTask
}
check {
    dependsOn(verificationTask)
}

将来,Gradle将会考虑这种错误,并且抛出一个异常。

  1. 喜欢小的增量变更。较小的更改更容易进行完整性检查。如果您破坏了构建逻辑,那么分析上一次成功验证以来的变更日志将会更加容易。
  2. 确保建立了验证构建逻辑的良好计划。通常,一个简单的构建任务调用就可以验证您的构建逻辑。然而,有些构建可能需要额外的验证——理解构建的行为并确保您有一个好的验证计划。
  3. 与手工测试相比,更喜欢自动测试。使用TestKit为构建逻辑编写集成测试是一个很好的实践。
  4. 避免按名称引用任务。在大多数情况下,按名称引用任务是一种脆弱的模式,应该避免。虽然任务名称在TaskProvider上可用,但是应该尽量使用强类型模型中的引用。
  5. 尽可能多地使用新的任务API。急于完成某些任务可能会导致其他任务的级联。使用TaskProvider可以帮助创建一个间接性实现,以防止传递性实现。
  6. 如果您试图从新API的配置块中访问某些API,则可能会禁用它们。例如,在配置用新API注册的任务时不能调用Project.afterEvaluate()。由于afterEvaluate用于延迟配置项目,将延迟配置与新API混合使用可能会导致难以诊断的错误,因为并不总是配置用新API注册的任务,但是可能期望afterEvaluate块总是执行

迁移步骤

迁移过程的第一部分是遍历代码并手动迁移迫切需要的任务创建和配置,以使用配置避免api。下面探讨成功迁移的建议步骤。在执行这些步骤时,请记住上面的指导原则。

在插件中使用新的API将要求用户使用Gradle 4.9或更高版本。插件作者应该参考支持Gradle section的旧版本。

  1. 迁移影响所有任务(任务)的任务配置。按类型(tasks.withType(…){})划分的所有{}或子集。这将导致您的构建急于创建由插件注册的更少的任务。
  2. 按名称配置的i篦任务。与前一点类似,这将导致您的构建急于创建更少的由插件注册的任务。例如,使用任务容器#getByName(String, Closure/Action)的逻辑应该转换为任务容器#named(String).configure(Closure/Action)。这还包括通过DSL块进行的任务配置。
  3. 将任务创建迁移到register(…)。此时,您应该在创建任务的任何地方进行更改,以注册这些任务。

对于以上所有步骤,请注意延迟配置的常见缺陷。

在进行这些更改之后,您应该会看到在配置时急切创建的任务数量的改进。使用构建扫描来了解哪些任务仍然在急切地创建,以及在哪里正在发生

故障排除

正在实现哪些任务?随着我们不断开发该特性,将提供更多的报告和故障排除信息来回答这个问题。同时,构建扫描是回答这个问题的最佳方法。遵循以下步骤:

  1. 创建构建扫描。使用--scan标志执行Gradle命令。

  2. 导航到configuration performance选项卡。
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-s43E7ViO-1569757514464)(https://docs.gradle.org/current/userguide/img/taskConfigurationAvoidance-navigate-to-performance.png)]
    图1所示,导航到“生成扫描”中的“配置性能”选项卡

    1. 从左侧菜单导航到性能卡。
    2. 从性能卡顶部导航到configuration选项卡。
  3. 所有的信息要求被展现
    https://docs.gradle.org/current/userguide/img/taskConfigurationAvoidance-performance-annotated.png
    图2,配置性能选项卡在构建扫描注释

    1. 创建或不创建每个任务时显示的总任务。
      • “立即创建”表示使用即时任务api创建的任务。
      • “在配置期间创建的”表示使用配置避免api创建的任务,但是是显式实现的(通过TaskProvider#get())或隐式使用急切的任务查询api。
      • “立即创建的”和“在配置期间创建的”数字都被认为是“坏的”数字,应该尽可能地将其最小化。
      • “在任务图计算期间创建”表示在构建执行任务图时创建的任务。理想情况下,这个数字应该等于执行的任务数量。
      • “未创建”表示在此构建会话中避免的任务。
    2. 下一节将帮助回答任务在何处实现的问题。对于每个脚本、插件或生命周期回调,最后一列表示立即或在配置期间创建的任务。理想情况下,这一列应该是空的。
    3. 关注脚本、插件或生命周期回调将显示创建的任务的细分。

陷阱

  • 小心隐藏的热切的任务实现。有许多方法可以急切地配置任务。例如,使用任务名和DSL块配置任务将会立即创建任务:
// Given a task lazily created with
tasks.register("someTask")

// Some time later, the task is configured using a DSL block
someTask {
    // This causes the task to be created and this configuration to be executed immediately
}

替换使用named()方法获取对任务的引用并配置它:

tasks.named("someTask").configure {
    // ...
    // Beware of the pitfalls here
}

类似地,Gradle也有语法糖,允许通过名称引用任务,而不需要显式的查询方法。这也会导致任务被立即创建:

tasks.register("someTask")

// Sometime later, an eager task is configured like
task anEagerTask {
    // The following will cause "someTask" to be looked up and immediately created
    dependsOn someTask
}

有几种方法可以避免这种过早的创造:

  • 使用TaskProvider变量。在同一构建脚本中多次引用任务时非常有用。
val someTask by tasks.registering

task("anEagerTask") {
    dependsOn(someTask)
}
  • 迁移消费的task到新的API
tasks.register("someTask")

tasks.register("anEagerTask") {
    dependsOn someTask
}
  • 懒加载方式查找任务, 当任务不是由相同的插件创建时非常有用。
tasks.register("someTask")

task("anEagerTask") {
    dependsOn(tasks.named("someTask"))
}
  • 编译浏览插件buildScanPublishPrevious任务直到1.15版本才会启动。升级构建扫描插件以使用最新版本。

Gradle_172">支持旧版本的Gradle

本节描述了两种方法,如果您必须保持与大于4.9的Gradle版本的兼容性,则可以使插件向后兼容旧版本的Gradle。大多数新的API方法都可以从Gradle 4.9开始使用。

虽然向后兼容性对用户很好,但我们仍然建议及时升级到更新的Gradle版本。这将减少您的维护负担。

保持兼容性的第一个方法是根据Gradle 4.9 API编译插件,并使用Groovy有条件地调用正确的API(例子)。

第二种方法是使用Java反射来处理编译期间api不可用的事实(例子)。

强烈建议使用TestKit和Gradle的多个版本进行跨版本测试。

  • 使用groovy.lang的方法。在新的API中,使用org.gradle.api.Action方法覆盖闭包。
  • 未来可能会根据用户反馈添加更多方便的方法。
  • 一些旧的API方法可能永远无法在新的API中直接替换。
  • 在通过配置避免方法注册的配置操作中访问某些api时,可能会受到限制。

Table


http://www.niftyadmin.cn/n/944685.html

相关文章

北京三日自驾游-和狗狗的秦皇岛之旅

前序 生活不止眼前的苟且,还有诗和远方 努力工作是为了更好的体验生活,需要偶尔停下脚步看看路旁的风景,所以我们趁着中秋放假,体验了一把秦皇岛3日自驾游,由于带上了狗,所以所有的去玩的地方和住宿的地方…

Lottie 浅析

Lottie 简介 Lottie是是一个可以解析Adobe After Effects使用BodyMovin插件导出的动画json文件,并且渲染到手机和网页上的库,Lottie支持Android,iOS,Web和Windows。 Lottie Android 如何使用 Lottie在Android仅支持Gradle的形…

放苹果

放苹果Time Limit: 1000MS Memory Limit: 10000KTotal Submissions: 30812 Accepted: 19451 Description 把M个同样的苹果放在N个同样的盘子里,允许有的盘子空着不放,问共有多少种不同的分法?(用K表示)5,1&…

程序员的蜕变之旅-健身

前言 我在《三年开发经验,抖音离职后,拿到Airbnb、快手、小红书、猿辅导等多家公司的offer》博客中也写到过,我一直在坚持健身,但是收效甚微,其实自从毕业后一直在保持着锻炼这个习惯,也曾一直梦想能锻炼出…

美国圣诞8日西海岸自驾游

一晃已经1年半过去了,2020年年初在美国西海岸的旅游事情,回来后总说抽个时间记录一下,但是总是因为懒,一直往后脱,这一脱就是1年半,正好中秋没有出去玩,天气也不好,伴随着窗外的雨&a…

一年Android工作经验,今日头条 阿里 百度 网易 美团 小米 快手面经

转载请注明出处:http://blog.csdn.net/a296777513/article/details/73610719 前言 人生困难重重,在漫长而艰辛的前行路上,坚持不懈、脚踏实地的“低头拉车”固然重要。但认清形势、找准目标的“抬头看路”也很关键,甚至决定着你能…

三年开发经验,抖音离职后,拿到Airbnb、快手、小红书、猿辅导等多家公司的offer

禁止任何形式的转载,已经收回了所有的转载权利,郑重声明,如果有侵犯到公司利益,请联系我,会进行修改。 前言 我这篇文章并不是简单的描述一些面试中的题,或者总结一些Android的知识,而是想记录我整个的想法和准备的过程,以及一些心得体会,让大家更加全面的去看待工作…

Tree Grafting(POJ 3437)

//思路&#xff1a; 二叉树中X节点的高 二叉树中X的父节点的高 X是第几个儿子 [cpp] view plaincopy #include <iostream> #include<string> using namespace std; string s; int i,n0,height1,height2; void work(int level1,int l…