自定义Gradle Task报错:非静态内部类问题求助
解决Gradle自定义Task非静态内部类报错问题
核心问题解决
报错的直接原因是MyTask被定义为非静态内部类,Gradle无法实例化这种类型的Task。以下是具体解决方法:
1. 将MyTask改为顶级类
如果你的MyTask写在模块的build.gradle.kts中,确保它位于脚本最外层,不要嵌套在任何类、函数或闭包内部:
// 放在build.gradle.kts最顶部,作为顶级类 abstract class MyTask : DefaultTask() { @get:Input abstract val moduleName: Property<String> @get:Input abstract val moduleArtifactId: Property<String> @get:Input abstract val repositoryUrl: Property<String> @TaskAction fun execute() { println("hello from my task, my name is ${moduleName.get()}, ${moduleArtifactId.get()}, ${repositoryUrl.get()}") project.publishing { publications { create<MavenPublication>("release") { groupId = project.properties["groupId"] as String version = project.properties["version"] as String artifactId = moduleArtifactId.get() project.afterEvaluate { from(components["release"]) } artifact("$buildDir/outputs/aar/$artifactId-release.aar") { classifier = "release" } } } repositories { maven { this.name = moduleName.get() this.url = uri(repositoryUrl.get()) credentials { username = "my-user-name" password = "my-password" } } } } } } // 注册Task tasks.register<MyTask>("mytask") { moduleName.set("module's name") moduleArtifactId.set("artifact's id") repositoryUrl.set("remote repo's url") }
如果需要在多模块复用该Task,更推荐将它放在buildSrc目录的顶级Kotlin文件中:
- 在项目根目录创建
buildSrc/src/main/kotlin/MyTask.kt - 将
MyTask类写入该文件作为顶级类 - 所有模块的
build.gradle.kts可直接引用该类,无需重复定义
2. 若必须嵌套则改为静态嵌套类(不推荐)
如果需要嵌套在其他类中,确保它是Kotlin的静态嵌套类(即不加inner关键字的嵌套类,Kotlin默认嵌套类为静态):
object TaskContainer { // 静态嵌套类,Gradle可实例化 abstract class MyTask : DefaultTask() { // ... 类内容同前 } } // 注册时引用静态嵌套类 tasks.register<TaskContainer.MyTask>("mytask") { moduleName.set("module's name") moduleArtifactId.set("artifact's id") repositoryUrl.set("remote repo's url") }
额外优化建议
你的Task逻辑存在潜在问题:在@TaskAction中配置publishing扩展,会导致发布配置仅在Task执行阶段初始化,违反Gradle配置/执行阶段分离原则。建议将发布配置移到配置阶段,Task仅负责触发发布:
abstract class MyTask : DefaultTask() { @get:Input abstract val moduleName: Property<String> @get:Input abstract val moduleArtifactId: Property<String> @get:Input abstract val repositoryUrl: Property<String> // 依赖发布任务,确保触发发布动作 init { val repoNameCapitalized = moduleName.get().replaceFirstChar { it.uppercase() } dependsOn("publishReleasePublicationTo${repoNameCapitalized}Repository") } @TaskAction fun execute() { println("开始发布模块: ${moduleName.get()},制品ID: ${moduleArtifactId.get()}") } } // 提取发布配置到单独函数,在配置阶段执行 fun Project.setupPublishing(artifactId: String, repoUrl: String, repoName: String) { publishing { publications { create<MavenPublication>("release") { groupId = project.properties["groupId"] as String version = project.properties["version"] as String this.artifactId = artifactId from(components["release"]) artifact("$buildDir/outputs/aar/$artifactId-release.aar") { classifier = "release" } } } repositories { maven { name = repoName url = uri(repoUrl) credentials { username = "my-user-name" password = "my-password" } } } } } // 注册Task时同时完成发布配置 tasks.register<MyTask>("mytask") { val repoName = "module's name" val artifactId = "artifact's id" val repoUrl = "remote repo's url" moduleName.set(repoName) moduleArtifactId.set(artifactId) repositoryUrl.set(repoUrl) // 配置阶段初始化发布设置 project.setupPublishing(artifactId, repoUrl, repoName) }
内容的提问来源于stack exchange,提问作者brzi_gonzales
相关产品推荐
相关产品推荐

