数据流操作支持是一项孵化功能,此处描述的详细信息可能会发生变化。

在 Gradle 构建中执行工作的首选方式是使用任务。然而,有些工作并不适合任务,例如构建失败的自定义处理。如果您想在构建成功时播放欢快的声音,在构建失败时播放悲伤的声音,该怎么办?该工件要处理任务执行结果,因此它本身不能是任务。

数据流操作 API 提供了一种安排此类工作的方法。数据流操作是一个参数化的隔离工作,一旦其所有输入参数可用,就可以执行。

实施数据流操作

第一步是实施行动本身。为此,您创建一个实现FlowAction接口的类。该execute方法必须被实现,因为这是工作发生的地方。操作实现被视为自定义 Gradle 类型,并且可以使用自定义 Gradle 类型可用的任何功能。特别是,一些 Gradle 服务可以注入到实现中。

数据流操作可以接受参数。要提供参数,您需要定义一个抽象类(或接口)来保存参数。参数类型必须实现(或扩展)FlowParameters。操作实现获取参数作为execute方法的参数。参数类型也是自定义的Gradle类型

当操作不需要参数时,您可以使用FlowParameters.None作为参数类型。

以下是采用共享构建服务和文件路径作为参数的数据流操作示例。

SoundPlay.java
package org.gradle.sample.sound;

import org.gradle.api.flow.FlowAction;
import org.gradle.api.flow.FlowParameters;
import org.gradle.api.provider.Property;
import org.gradle.api.services.ServiceReference;
import org.gradle.api.tasks.Input;

import java.io.File;

public abstract class SoundPlay implements FlowAction<SoundPlay.Parameters> {
    interface Parameters extends FlowParameters {
        @ServiceReference (1)
        Property<SoundService> getSoundService();

        @Input (2)
        Property<File> getMediaFile();
    }

    @Override
    public void execute(Parameters parameters) {
        parameters.getSoundService().get().playSoundFile(parameters.getMediaFile().get());
    }
}
1 参数类型中的参数必须被注释。如果参数带有注释,@ServiceReference则在创建操作时,根据通常的规则,会自动将合适的共享构建服务实现分配给该参数。
2 所有其他参数必须用 注释@Input

生命周期事件提供者

除了通常的值提供程序之外,Gradle 还为构建生命周期事件(例如构建完成)提供了专用提供程序。这些提供程序旨在用于数据流操作,并在用作输入时提供额外的排序保证。如果您通过调用map或 等方式从事件提供程序派生提供​​程序,则该顺序也适用flatMap。您可以从FlowProviders类获取这些提供程序。

如果您不使用生命周期事件提供程序作为数据流操作的输入,则执行操作的确切时间未定义,并且可能会在下一版本的 Gradle 中发生变化。

提供执行操作

您不应该FlowAction手动创建对象。相反,您请求在适当的范围内执行它们FlowScope。执行此操作时,您可以配置要使用的任务的参数。

SoundFeedbackPlugin.java
package org.gradle.sample.sound;

import org.gradle.api.Plugin;
import org.gradle.api.flow.FlowProviders;
import org.gradle.api.flow.FlowScope;
import org.gradle.api.initialization.Settings;

import javax.inject.Inject;
import java.io.File;

public abstract class SoundFeedbackPlugin implements Plugin<Settings> {
    @Inject
    protected abstract FlowScope getFlowScope(); (1)

    @Inject
    protected abstract FlowProviders getFlowProviders(); (1)

    @Override
    public void apply(Settings settings) {
        final File soundsDir = new File(settings.getSettingsDir(), "sounds");
        getFlowScope().always( (2)
            SoundPlay.class,  (3)
            spec ->  (4)
                spec.getParameters().getMediaFile().set(
                    getFlowProviders().getBuildWorkResult().map(result -> (5)
                        new File(
                            soundsDir,
                            result.getFailure().isPresent() ? "sad-trombone.mp3" : "tada.mp3"
                        )
                    )
                )
        );
    }
}
1 使用服务注入来获取FlowScope实例FlowProviders。它们可用于项目和设置插件。
2 使用适当的范围来运行您的操作。顾名思义,always每次构建运行时都会执行范围内的操作。
3 指定实现该操作的类。
4 使用spec参数来配置操作参数。
5 生命周期事件提供者可以映射到其他东西,同时保留操作顺序。

因此,当您运行构建并成功完成时,该操作将播放“tada”声音。如果构建在配置或执行时失败,那么您会听到“悲伤的长号”——当然,假设构建配置进行得足够远,足以注册操作。