必须用 tasks.register() 而不是 task,因其延迟注册符合增量构建要求;task 会立即配置导致性能下降、注解失效及 AGP 8.0+ 构建失败。

Gradle 插件注册自定义任务,核心就一条:在插件的 apply() 方法里调用 project.tasks.register(),不能靠 task 闭包或 create() —— 后两者会立即执行配置,破坏增量构建和生命周期管理。
为什么必须用 tasks.register() 而不是 task?
旧写法 task myTask { ... } 是立即配置(eager configuration),会在 Gradle 配置阶段就初始化任务对象,哪怕你根本没打算运行它。这会导致:
- 插件加载变慢,尤其当任务内部读取大量文件或依赖复杂逻辑时
- 无法安全使用
@Input/@OutputFile声明,Gradle 会报Cannot change dependencies of configuration类错误 - 与 Android Gradle Plugin 8.0+ 的严格配置检查冲突,直接构建失败
而 tasks.register() 是延迟注册(lazy registration),只声明任务骨架,真正初始化发生在执行阶段,符合现代 Gradle 最佳实践。
register() 的三种典型调用方式
注册本身不复杂,但参数传递方式决定你能否灵活控制任务行为:
-
仅注册类名和任务名:
project.tasks.register("myTask", MyCustomTask.class)—— 最轻量,适合无参数、纯逻辑任务 -
注册 + DSL 配置块:
project.tasks.register("myTask", MyCustomTask.class) { description = "生成签名密钥"; group = "build" }—— 推荐日常使用,可设group、description、输入输出属性 -
注册后单独配置:
project.tasks.register("myTask", MyCustomTask.class); project.tasks.named("myTask", MyCustomTask.class).configure { inputText.set("custom value") }—— 适用于需跨模块复用或条件注入配置的场景
Android 项目中注册时的两个硬性要求
如果你的插件要被 AGP(Android Gradle Plugin)正确识别并参与构建流程,必须满足:
- 自定义任务类必须继承
DefaultTask,且方法上标注@TaskAction(不能是普通void run()) - 所有输入输出字段必须用
@Input、@InputFile、@OutputDirectory等注解显式声明,否则 Gradle 无法做增量判断,每次都会重新执行
例如,漏掉 @OutputFile 导致 myTask 每次都跑,哪怕输出文件没变 —— 这不是 bug,是 Gradle 明确拒绝缓存未声明输出的任务。
buildSrc 和独立插件里的注册位置差异
注册代码写在哪,取决于你插件的组织形式:
-
buildSrc 方式:在
buildSrc/src/main/groovy/MyPlugin.groovy或buildSrc/src/main/kotlin/MyPlugin.kt的apply()方法内调用project.tasks.register() -
独立插件项目:在实现
Plugin<project></project>的类中(如MyPlugin.java)的apply()方法里注册;同时确保gradlePlugin { plugins { ... } }块已正确定义插件 ID 和实现类
容易忽略的是:独立插件的 JAR 必须包含 META-INF/gradle-plugins/xxx.properties 文件,内容为 implementation-class=com.example.MyPlugin,否则 plugins { id 'com.example.myplugin' } 会找不到类。


















