我正在尝试遵循 Gradle custom plugin documentation创建一个可以配置的插件。
我的插件代码:
interface MyExtension {
var myValue: Property<String>
}
class MyPlugin : Plugin<Project> {
override fun apply(project: Project) {
val extension = project.extensions.create<MyExtension>("myExt")
}
}
在 build.gradle.kts
:
plugins {
`java-library`
}
apply<MyPlugin>()
the<MyExtension>().myValue.set("some-value")
运行这个将会给出
Build file '<snip>/build.gradle.kts' line: 6
java.lang.NullPointerException (no error message)
结果是the<MyExtension>().myValue
是 null
,所以set
调用失败。我该如何正确地做到这一点?我是否遗漏了文档中的某些内容,或者只是错误的?
最佳答案
文档没有错误。属性可以由您或 Gradle 管理。对于后者,必须满足一定的条件。
没有托管属性
如果您想完全掌控,您可以实例化您自己声明的任何变量。例如,要在作为接口(interface)的扩展上声明属性,它可能如下所示:
override fun apply(project: Project) {
val extension = project.extensions.create("myExt", MyExtension::class.java)
extension.myValue = project.objects.property(String::class.java)
}
或者您可以通过将其设为类来直接在扩展中实例化它:
open class MessageExtension(objects: ObjectFactory) {
val myValue: Property<String> = objects.property(String::class.java)
}
但是,属性字段实际上并不应该具有 setter,因为属性本身同时具有 setter 和 getter。因此,您通常应该避免第一种方法并删除第二种方法的 setter 。
参见here有关自行管理特性的更多示例。
具有托管属性
为了帮助您减少样板代码,Gradle 可以使用所谓的“托管属性”为您实例化属性。要使用它们,属性必须没有有setter,并且getter应该是抽象的(它隐式地位于接口(interface)上)。因此,您可以返回第一个示例并通过将 var
更改为 val
来修复它:
interface MyExtension {
val myValue: Property<String> // val (getter only)
}
现在 Gradle 将为您实例化该字段。同样的事情也适用于抽象类。
在文档 here 中了解有关托管属性的更多信息.
关于kotlin - 使用自定义插件时 Gradle 提供的 Null 属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70064307/