通过在 Build 脚本中创建一个简单任务,学习编写 Gradle 任务的基础知识。

在本节中,你将

  • 理解任务

  • 为插件创建自定义任务

步骤 0. 开始之前

  1. 你已经在第 1 部分中初始化了 Java 应用。

  2. 你已经在第 2 部分中理解了 Gradle 构建生命周期。

  3. 你已经在第 3 部分中添加了一个子项目和独立的构建。

  4. 你已经在第 4 部分中查看了一个 Settings 文件。

  5. 你已经在第 5 部分中编写了一个 Build 脚本。

步骤 1. 理解任务

任务 (Task) 是一个可执行的代码片段,其中包含一系列操作 (actions)。

操作 (actions) 通过 doFirst{}doLast{} 闭包添加到任务 (Task) 中。

一个任务可以依赖于其他任务。

步骤 2. 注册和配置任务

在教程早期,我们在 app 构建脚本中注册并配置了 task1

app/build.gradle.kts
tasks.register("task1"){  (1)
    println("REGISTER TASK1: This is executed during the configuration phase")
}

tasks.named("task1"){  (2)
    println("NAMED TASK1: This is executed during the configuration phase")
    doFirst {
        println("NAMED TASK1 - doFirst: This is executed during the execution phase")
    }
    doLast {
        println("NAMED TASK1 - doLast: This is executed during the execution phase")
    }
}
1 你可以使用 register() 方法创建新任务。
2 你可以使用 named() 方法配置现有任务。
app/build.gradle
tasks.register("task1") {  (1)
    println("REGISTER TASK1: This is executed during the configuration phase")
}

tasks.named("task1") {  (2)
    println("NAMED TASK1: This is executed during the configuration phase")
    doFirst {
        println("NAMED TASK1 - doFirst: This is executed during the execution phase")
    }
    doLast {
        println("NAMED TASK1 - doLast: This is executed during the execution phase")
    }
}
1 你可以使用 register() 方法创建新任务。
2 你可以使用 named() 方法配置现有任务。

步骤 3. 创建自定义任务

要创建自定义任务,必须在 Groovy DSL 中继承 DefaultTask 类,或者在 Kotlin DSL 中继承 DefaultTask 类。

使用以下代码创建一个名为 LicenseTask 的自定义类,并将其添加到 gradle/license-plugin/plugin/src/main/kotlin/license/LicensePlugin.ktgradle/license-plugin/plugin/src/main/groovy/license/LicensePlugin.groovy 文件的底部。

gradle/license-plugin/plugin/src/main/kotlin/license/LicensePlugin.kt
import org.gradle.api.Project
import org.gradle.api.Plugin
import org.gradle.api.DefaultTask
import org.gradle.api.tasks.Input
import org.gradle.api.tasks.TaskAction
import java.io.File
import java.io.InputStream
import java.nio.charset.Charset

class LicensePlugin: Plugin<Project> {
    // Don't change anything here
}

abstract class LicenseTask : DefaultTask() {
    @Input
    val licenseFilePath = project.layout.settingsDirectory.file("license.txt").asFile.path

    @TaskAction
    fun action() {
        // Read the license text
        val licenseText = File(licenseFilePath).readText()
        // Walk the directories looking for java files
        project.layout.settingsDirectory.asFile.walk().forEach {
            if (it.extension == "java") {
                // Read the source code
                var ins: InputStream = it.inputStream()
                var content = ins.readBytes().toString(Charset.defaultCharset())
                // Write the license and the source code to the file
                it.writeText(licenseText + content)
            }
        }
    }
}
gradle/license-plugin/plugin/src/main/groovy/license/LicensePlugin.groovy
import org.gradle.api.Project
import org.gradle.api.Plugin
import org.gradle.api.DefaultTask
import org.gradle.api.tasks.Input
import org.gradle.api.tasks.TaskAction

class LicensePlugin implements Plugin<Project> {
    // Don't change anything here
}

abstract class LicenseTask extends DefaultTask {
    @Input
    def licenseFilePath = project.layout.settingsDirectory.file("license.txt").asFile.path

    @TaskAction
    void action() {
        // Read the license text
        def licenseText = new File(licenseFilePath).text
        // Walk the directories looking for java files
        project.layout.settingsDirectory.asFile.eachFileRecurse { file ->
            int lastIndexOf = file.getName().lastIndexOf('.')
            if ((lastIndexOf != -1) && (file.getName().substring(lastIndexOf)) == ".java") {// Read the source code
                def content = file.getText()
                //println(licenseText + '\n' + content)
                // Write the license and the source code to the file
                file.text = licenseText + '\n' + content
            }
        }
    }
}

LicenseTask 类封装了任务的操作逻辑,并声明了任务预期的任何输入和输出。

任务操作使用 @TaskAction 注解。在其中,逻辑首先找到一个名为 "license.txt" 的文件。此文件包含 Apache 许可证的文本。

license.txt
/*
* Licensed under the Apache License
*/

然后,任务查找扩展名为 .java 的文件,并添加许可证头。

该任务有一个输入,即许可证文件名,使用 @Input 注解。

Gradle 使用 @Input 注解来判断任务是否需要运行。如果任务以前从未运行过,或者自上次执行以来输入值已更改,则 Gradle 将执行该任务。

尽管已经创建了一个自定义类,但尚未将其添加到 LicensePlugin 中。目前无法运行 LicenseTask

目前你只需要确保 ./gradlew build 能够成功运行而不会失败。

$ ./gradlew build

SETTINGS FILE: This is executed during the initialization phase

> Configure project :app
BUILD SCRIPT: This is executed during the configuration phase

BUILD SUCCESSFUL in 1s
13 actionable tasks: 6 executed, 7 up-to-date

下一步: 编写插件 >>