gradle跳过任务的关键是显式准确声明inputs和outputs:inputs需覆盖源文件、配置参数等所有影响结果的要素,outputs需包含实际生成的文件或目录;自定义task须用@input、@output等注解标注,验证方式为二次执行时显示up-to-date。

要让 Gradle 正确跳过已执行且输入未变的任务(即实现缓存跳过),关键不是“开启缓存开关”,而是**显式、准确地声明 task 的 inputs 和 outputs**。Gradle 会基于这些声明自动判断任务是否 up-to-date,从而跳过执行。配置错误或遗漏会导致缓存失效、重复执行,甚至误判为最新而跳过本该运行的任务。
inputs 和 outputs 必须覆盖所有影响结果的要素
Gradle 不会自动扫描代码或文件系统来推断哪些东西变了——它只信任你明确声明的内容。只要 inputs 或 outputs 中任一值变化,任务就会重新执行;反之,全部一致才会被标记为 UP-TO-DATE 并跳过。
- inputs 应包含:源文件、配置参数(如版本号、开关标志)、模板内容、依赖的外部资源路径等——任何可能导致输出不同的因素
- outputs 应包含:生成的 class 文件目录、写入的 properties 文件、打包的 jar 路径等——所有该 task 实际产出的文件或目录
- 避免把无关变量(比如当前时间戳、随机数)放进 inputs,否则每次都会触发重执行
在 build.gradle 中正确声明方式
使用 inputs 和 outputs DSL 属性,在 task 配置块中直接赋值,确保它们在配置阶段就可读取(不能延迟到 doLast 里计算):
-
单个文件输入:
inputs.file 'src/main/resources/config.template' -
整个目录输入:
inputs.dir 'src/main/java' -
简单属性输入:
inputs.property('isRelease', project.version.release) -
多个文件输出:
outputs.files 'build/generated/Constants.java', 'build/generated/version.properties' -
输出目录:
outputs.dir 'build/classes/java/main'
自定义 Task 类需配合注解
如果你编写的是自定义 task 类(继承 DefaultTask),必须用 Gradle 提供的注解标注 getter 方法,才能被增量构建识别:
-
@Input:用于简单类型(String、boolean、int 等)或可序列化对象 -
@InputFile/@InputDirectory:用于单个文件或目录 -
@OutputFile/@OutputDirectory:用于产出的文件或目录 -
@Nested:用于封装了多个 input/output 属性的嵌套对象(需其内部字段也加对应注解)
例如一个模板生成 task,它的类中应有:
public class GenerateFromTemplate extends DefaultTask {
@InputFile
public RegularFileProperty getTemplate() { ... }
@Input
public Property<string> getDataJson() { ... }
@OutputFile
public RegularFileProperty getOutputFile() { ... }
}</string>
验证是否生效的简单方法
执行两次相同构建命令(如 ./gradlew build),观察目标 task 输出行:
- 首次运行显示
:taskName(执行中) - 第二次若看到
:taskName UP-TO-DATE,说明 inputs/outputs 声明成功,Gradle 已跳过该 task - 如果仍显示
EXECUTING,检查是否漏了某个输入(比如忘记声明某配置文件)、outputs 路径写错、或 task 内部逻辑在 doLast 中修改了未声明的输出文件
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











