Gradle 现代化任务依赖方案

Gradle 现代化任务依赖方案

传统任务依赖模式的痛点

🧩 典型传统实现

kotlin 复制代码
// 文件写入任务

open class OldWriter : DefaultTask() {

@get:Input

val list: MutableList<String> = mutableListOf()

@get:OutputFile

lateinit var outputFile: File

@TaskAction

fun write() = outputFile.writeText(list.joinToString("\n"))

}

  


// 文件读取任务

open class OldReader : DefaultTask() {

@get:InputFile

lateinit var inputFile: File

@get:OutputFile

lateinit var outputFile: File

@TaskAction

fun writeCount() = outputFile.writeText("Line count: ${inputFile.readLines().count()}")

}

  


// 任务配置

val oldWriterFile = project.buildDir.resolve("oldWriter.txt")

val oldWriterTask = tasks.register("oldWriter", OldWriter::class) {

list.addAll(listOf("apple", "orange", "banana"))

outputFile = oldWriterFile

}

  


tasks.register("oldReader", OldReader::class) {

inputFile = oldWriterFile

dependsOn(oldWriterTask) // 显式声明依赖

outputFile = project.buildDir.resolve("oldReader.txt")

}

⚠️ 架构缺陷分析

  1. 强耦合依赖声明

dependsOn(oldWriterTask)成为关键负载点,重构时易被误删,导致任务链断裂

graph LR A[用户执行任务] --> B{是否包含oldWriter?} B -->|否| C[oldReader失败] B -->|是| D[执行成功]
  1. 空安全风险

使用lateinit伪非空声明,实际依赖手动初始化顺序,配置错误将引发运行时异常

  1. 静态文件路径

硬编码文件路径使任务难以复用,路径变更需多处修改


现代化Property API解决方案

🚀 改进后实现方案

kotlin 复制代码
// 抽象化写入任务

abstract class NewWriter : DefaultTask() {

@get:Input

abstract val list: ListProperty<String> // 抽象属性

@get:OutputFile

abstract val outputFile: RegularFileProperty // 文件属性封装

@TaskAction

fun write() {

outputFile.get().asFile.writeText(list.get().joinToString("\n"))

}

}

  


// 抽象化读取任务

abstract class NewReader : DefaultTask() {

@get:InputFile

abstract val inputFile: RegularFileProperty

@get:OutputFile

abstract val outputFile: RegularFileProperty

@TaskAction

fun writeCount() {

val count = inputFile.get().asFile.readLines().count()

outputFile.get().asFile.writeText("Line count $count")

}

}

  


// 自动化连接配置

val newWriterTask = tasks.register("newWriter", NewWriter::class) {

list.addAll("apple", "orange", "banana")

outputFile.set(layout.buildDirectory.file("newWriter.txt")) // 延迟绑定路径

}

  


tasks.register("newReader", NewReader::class) {

// 自动建立任务依赖

inputFile.set(newWriterTask.flatMap { it.outputFile })

outputFile.set(layout.buildDirectory.file("newReader.txt"))

}

💡 核心技术突破

  1. 隐式依赖连接

flatMap操作符自动建立任务依赖链:

kotlin 复制代码
inputFile.set(newWriterTask.flatMap { it.outputFile })
  • 当解析inputFile时自动触发newWriterTask执行

  • 依赖关系声明与任务逻辑解耦

  1. 类型安全属性

采用Gradle提供的属性抽象类:

kotlin 复制代码
abstract val outputFile: RegularFileProperty
  • 内置空安全检查

  • 支持延迟计算(Lazy Evaluation)

  1. 动态路径绑定

通过layout.buildDirectory动态构建路径:

kotlin 复制代码
outputFile.set(layout.buildDirectory.file("newWriter.txt"))
  • 路径变更不影响任务逻辑

  • 支持跨项目复用


深度实践案例

🌐 多阶段数据处理流水线

kotlin 复制代码
// 数据生成

abstract class DataGenTask : DefaultTask() {

@get:OutputFile

abstract val dataset: RegularFileProperty

@TaskAction

fun generate() {

dataset.get().asFile.writeText((1..1000).joinToString(","))

}

}

  


// 数据分析

abstract class DataAnalyzer : DefaultTask() {

@get:InputFile

abstract val sourceData: RegularFileProperty

@get:OutputFile

abstract val report: RegularFileProperty

@TaskAction

fun analyze() {

val data = sourceData.get().asFile.readText().split(",")

val stats = """

Count: ${data.size}

Min: ${data.minOf { it.toInt() }}

Max: ${data.maxOf { it.toInt() }}

""".trimIndent()

report.get().asFile.writeText(stats)

}

}

  


// 自动构建流水线

val genTask = tasks.register("generateData", DataGenTask::class) {

dataset.set(layout.buildDirectory.file("dataset.csv"))

}

  


tasks.register("analyzeData", DataAnalyzer::class) {

sourceData.set(genTask.flatMap { it.dataset }) // 自动连接

report.set(layout.buildDirectory.file("report.txt"))

}

🔧 进阶技巧:跨任务数据传递

kotlin 复制代码
// 传递结构化数据

abstract class JsonProcessor : DefaultTask() {

@get:OutputFile

abstract val jsonOutput: RegularFileProperty

@TaskAction

fun process() {

val data = mapOf("items" to listOf("A", "B", "C"))

jsonOutput.get().asFile.writeText(Json.encodeToString(data))

}

}

  


abstract class DataLoader : DefaultTask() {

@get:InputFile

abstract val jsonInput: RegularFileProperty

@TaskAction

fun load() {

val content = jsonInput.get().asFile.readText()

val data = Json.decodeFromString<Map<String, List<String>>>(content)

println("Loaded items: ${data["items"]?.joinToString()}")

}

}

  


// 自动化JSON管道

val processor = tasks.register("processJson", JsonProcessor::class) {

jsonOutput.set(layout.buildDirectory.file("data.json"))

}

  


tasks.register("loadData", DataLoader::class) {

jsonInput.set(processor.flatMap { it.jsonOutput })

}

新旧方案对比评估

| 维度 | 传统dependsOn方案 | Property API方案 |

|---------------------|----------------------------------|--------------------------------|

| 依赖声明 | 显式声明dependsOn | 隐式通过flatMap连接 |

| 空安全 | 依赖lateinit,运行时可能崩溃 | 编译时类型检查 |

| 任务触发时机 | 需手动管理执行顺序 | 按需自动触发依赖任务 |

| 配置重构安全性 | 高敏感,易因配置遗漏失败 | 低敏感,核心逻辑与配置解耦 |

| 跨模块复用 | 路径硬编码,复用困难 | 动态路径绑定,支持灵活复用 |


💎 总结:构建现代化的Gradle任务链

::: tabs

@tab 核心优势

  1. 依赖自动化

通过flatMap实现任务自动连接,消除显式dependsOn声明

  1. 类型安全革命

RegularFileProperty等抽象属性取代lateinit var,编译期保障空安全

  1. 资源延迟绑定

layout.buildDirectory.file()实现路径动态解析,支持环境适配

@tab 最佳实践

  1. 抽象化任务
kotlin 复制代码
abstract class ModernTask : DefaultTask() {

@get:InputFile

abstract val input: RegularFileProperty

}
  1. 链式连接
kotlin 复制代码
taskB.input.set(taskA.flatMap { it.output })
  1. 动态路径
kotlin 复制代码
output.set(layout.buildDirectory.file("dynamic.txt"))

@tab 迁移路线

graph TD A[识别dependsOn声明] --> B[提取关联任务输出] B --> C[替换为RegularFileProperty] C --> D[使用flatMap连接] D --> E[删除显式dependsOn]

:::

当代码中出现dependsOn时,应视为技术债务信号。现代Gradle的Property API通过类型安全的声明式编程,将任务连接从"命令式胶水代码"进化为"声明式数据管道",从根本上提升构建系统的可靠性和可维护性。🎯
原文:xuanhu.info/projects/it...

相关推荐
小趴菜82275 小时前
Android TabLayout使用记录
android
梦终剧5 小时前
【Android之路】 Kotlin 的 data class、enum class、sealed interface
android·开发语言·kotlin
折翅鵬14 小时前
Android 程序员如何系统学习 MQTT
android·学习
折翅鵬14 小时前
Kotlin Value Class 全面解析:类型安全与零开销封装
kotlin
搬砖的小码农_Sky14 小时前
如何将安卓应用迁移到鸿蒙?
android·华为·harmonyos
搬砖的小码农_Sky14 小时前
鸿蒙应用开发和安卓应用开发的区别
android·华为·harmonyos
2501_9160074714 小时前
iOS 混淆与团队协作,研发、安全、运维、测试如何在加固流程中高效配合(iOS 混淆、ipa 加固、协作治理)
android·ios·小程序·https·uni-app·iphone·webview
飞猿_SIR16 小时前
基于海思Hi3798MV200Android7.0聊聊HDMI色深模式和电视HDR
android·嵌入式硬件·音视频
come1123417 小时前
ptyhon 基础语法学习(对比php)
android·学习
ClassOps17 小时前
Android 12 SplashScreen启动屏
android·kotlin