这个章节介绍了处理任务时"避免配置",并且解释了迁移构建以有效实用配置避免api的一些指导原则,这里描述的API与现有的API共存,但是现有的API将在以后的几个重要版本中被代替。在Gradle 5.1中,我们建议使用配置避免的API来创建自定义的Plugins。
在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()
。使用这两个方法,将会触发创建和配置任务流程。
接下来将介绍一些我们在迁移过程中需要遵循的一般准则,和一些建议。我们还将介绍一些故障排除和陷阱,以帮助您解决迁移过程中可能遇到的一些问题。
help
任务作为一个基准在迁移的过程中。help
任务时一个完美的候选基准对于你的迁移过程。val check by tasks.registering
tasks.register("verificationTask") {
// Configure verificationTask
// Run verificationTask when someone runs check
check.get().dependsOn(this)
}
执行gradle
检查任务应该执行verificationTask
,但是在这个例子中,它不会执行。这是因为verificationTask
和check
之间的依赖关系只在verificationTask
实现时才会发生。为了避免此类问题,您必须只修改与配置操作关联的任务。其他任务应该在它们自己的配置操作中进行修改。代码将变成:
val check by tasks.registering
val verificationTask by tasks.registering {
// Configure verificationTask
}
check {
dependsOn(verificationTask)
}
将来,Gradle将会考虑这种错误,并且抛出一个异常。
迁移过程的第一部分是遍历代码并手动迁移迫切需要的任务创建和配置,以使用配置避免api。下面探讨成功迁移的建议步骤。在执行这些步骤时,请记住上面的指导原则。
在插件中使用新的API将要求用户使用Gradle 4.9或更高版本。插件作者应该参考支持Gradle section的旧版本。
对于以上所有步骤,请注意延迟配置的常见缺陷。
在进行这些更改之后,您应该会看到在配置时急切创建的任务数量的改进。使用构建扫描来了解哪些任务仍然在急切地创建,以及在哪里正在发生
正在实现哪些任务?随着我们不断开发该特性,将提供更多的报告和故障排除信息来回答这个问题。同时,构建扫描是回答这个问题的最佳方法。遵循以下步骤:
创建构建扫描。使用--scan
标志执行Gradle命令。
导航到configuration performance
选项卡。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-s43E7ViO-1569757514464)(https://docs.gradle.org/current/userguide/img/taskConfigurationAvoidance-navigate-to-performance.png)]
图1所示,导航到“生成扫描”中的“配置性能”选项卡
configuration
选项卡。// 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)
}
tasks.register("someTask")
tasks.register("anEagerTask") {
dependsOn someTask
}
tasks.register("someTask")
task("anEagerTask") {
dependsOn(tasks.named("someTask"))
}
buildScanPublishPrevious
任务直到1.15版本才会启动。升级构建扫描插件以使用最新版本。本节描述了两种方法,如果您必须保持与大于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