使用自定义插件时 Gradle 提供的 Null 属性
Null property provided by Gradle when using custom plugin
我正在尝试按照 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 管理。对于后者,需要满足一定的条件。
没有托管属性
如果你想完全掌控,你可以实例化你自己声明的任何变量。例如,要在作为接口的扩展上声明 属性,它可能如下所示:
override fun apply(project: Project) {
val extension = project.extensions.create("myExt", MyExtension::class.java)
extension.myValue = project.objects.property(String::class.java)
}
或者您可以直接在扩展中实例化它,方法是将其设为 class:
open class MessageExtension(objects: ObjectFactory) {
val myValue: Property<String> = objects.property(String::class.java)
}
但是,属性 字段实际上不应该具有 setter,因为 属性 本身同时具有 setter 和 getter。所以你通常应该避免第一种方法并在第二种方法中删除 setter。
有关自行管理属性的更多示例,请参阅 here。
具有托管属性
为了帮助您减少样板代码,Gradle 可以使用所谓的托管属性 为您实例化属性。要使用这些,属性 必须 而不是 有一个 setter,并且 getter 应该是抽象的(它隐含在接口上) .所以你可以回到你的第一个例子并通过将 var
更改为 val
:
来修复它
interface MyExtension {
val myValue: Property<String> // val (getter only)
}
现在 Gradle 将为您实例化该字段。同样的事情适用于抽象 classes.
在文档 here 中阅读有关托管属性的更多信息。
我正在尝试按照 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 管理。对于后者,需要满足一定的条件。
没有托管属性
如果你想完全掌控,你可以实例化你自己声明的任何变量。例如,要在作为接口的扩展上声明 属性,它可能如下所示:
override fun apply(project: Project) {
val extension = project.extensions.create("myExt", MyExtension::class.java)
extension.myValue = project.objects.property(String::class.java)
}
或者您可以直接在扩展中实例化它,方法是将其设为 class:
open class MessageExtension(objects: ObjectFactory) {
val myValue: Property<String> = objects.property(String::class.java)
}
但是,属性 字段实际上不应该具有 setter,因为 属性 本身同时具有 setter 和 getter。所以你通常应该避免第一种方法并在第二种方法中删除 setter。
有关自行管理属性的更多示例,请参阅 here。
具有托管属性
为了帮助您减少样板代码,Gradle 可以使用所谓的托管属性 为您实例化属性。要使用这些,属性 必须 而不是 有一个 setter,并且 getter 应该是抽象的(它隐含在接口上) .所以你可以回到你的第一个例子并通过将 var
更改为 val
:
interface MyExtension {
val myValue: Property<String> // val (getter only)
}
现在 Gradle 将为您实例化该字段。同样的事情适用于抽象 classes.
在文档 here 中阅读有关托管属性的更多信息。