Skip to content

自定义任务类

自定义任务类可以将可复用的构建逻辑封装为独立的类,支持类型安全的配置和增量构建。

基本自定义任务

在构建脚本中定义

kotlin
// build.gradle.kts
abstract class GreetTask : DefaultTask() {
    @get:Input
    abstract val greeting: Property<String>
    
    @get:Input
    abstract val name: Property<String>
    
    @TaskAction
    fun greet() {
        println("${greeting.get()}, ${name.get()}!")
    }
}

tasks.register<GreetTask>("greet") {
    greeting = "Hello"
    name = "Gradle"
}

@Input / @Output 注解

注解是增量构建的基础,Gradle 通过它们追踪任务的输入和输出:

kotlin
abstract class GenerateTask : DefaultTask() {
    // 输入:文件
    @get:InputFile
    abstract val templateFile: RegularFileProperty
    
    // 输入:目录
    @get:InputDirectory
    abstract val sourceDir: DirectoryProperty
    
    // 输入:属性值
    @get:Input
    abstract val packageName: Property<String>
    
    // 输入:可选属性
    @get:Input
    @get:Optional
    abstract val encoding: Property<String>
    
    // 输出:文件
    @get:OutputFile
    abstract val outputFile: RegularFileProperty
    
    // 输出:目录
    @get:OutputDirectory
    abstract val outputDir: DirectoryProperty
    
    @TaskAction
    fun generate() {
        val template = templateFile.get().asFile.readText()
        val pkg = packageName.get()
        val enc = encoding.getOrElse("UTF-8")
        
        val output = template.replace("__PACKAGE__", pkg)
        outputFile.get().asFile.writeText(output, charset(enc))
    }
}

tasks.register<GenerateTask>("generateSources") {
    templateFile.set(layout.projectDirectory.file("templates/MyClass.java.template"))
    sourceDir.set(layout.projectDirectory.dir("src/main/java"))
    packageName.set("com.example.generated")
    outputFile.set(layout.buildDirectory.file("generated/MyClass.java"))
}

常用注解

注解说明
@Input输入属性(基本类型、String、枚举等)
@InputFile输入文件
@InputFiles输入文件集合
@InputDirectory输入目录
@OutputFile输出文件
@OutputFiles输出文件集合
@OutputDirectory输出目录
@Optional可选(属性值可为 null)
@Classpathclasspath(内容敏感)
@Internal内部属性(不影响增量构建)
@Destroys该任务会删除的文件
@LocalState本地状态文件(不参与缓存)

在 buildSrc 中定义任务

将自定义任务放入 buildSrc 可以在所有子项目中共享:

buildSrc/
├── build.gradle.kts
└── src/main/kotlin/
    └── com/example/gradle/
        └── GenerateTask.kt
kotlin
// buildSrc/src/main/kotlin/com/example/gradle/GenerateTask.kt
package com.example.gradle

import org.gradle.api.DefaultTask
import org.gradle.api.file.RegularFileProperty
import org.gradle.api.provider.Property
import org.gradle.api.tasks.*

abstract class GenerateTask : DefaultTask() {
    @get:Input
    abstract val className: Property<String>
    
    @get:OutputFile
    abstract val outputFile: RegularFileProperty
    
    @TaskAction
    fun generate() {
        val code = "public class ${className.get()} {}"
        outputFile.get().asFile.writeText(code)
    }
}

使用:

kotlin
// 任意子项目的 build.gradle.kts
import com.example.gradle.GenerateTask

tasks.register<GenerateTask>("generateModel") {
    className.set("UserModel")
    outputFile.set(layout.buildDirectory.file("generated/UserModel.java"))
}

下一步