Android Kotlin:使用自定义setter时无延迟初始化的解决方法?
在我的活动中,我有一个字段应该是不可为空的,并且有一个自定义setter。我想初始化我的Android Kotlin:使用自定义setter时无延迟初始化的解决方法?,android,kotlin,Android,Kotlin,在我的活动中,我有一个字段应该是不可为空的,并且有一个自定义setter。我想初始化我的onCreate方法中的字段,所以我在变量声明中添加了lateinit。但是,显然你现在不能这么做 以下是我可以看到的变通方法: 用Java的方式来做。使该字段可为null,并用null初始化它。我不想那样做 使用该类型的“默认实例”初始化字段。我现在就是这么做的。但对于某些类型来说,这太贵了 是否有人可以推荐一种更好的方法(不涉及删除自定义setter)?将其替换为由nullable属性支持的属性: p
onCreate
方法中的字段,所以我在变量声明中添加了lateinit
。但是,显然你现在不能这么做
以下是我可以看到的变通方法:
- 用Java的方式来做。使该字段可为null,并用null初始化它。我不想那样做
- 使用该类型的“默认实例”初始化字段。我现在就是这么做的。但对于某些类型来说,这太贵了
是否有人可以推荐一种更好的方法(不涉及删除自定义setter)?将其替换为由nullable属性支持的属性:
private var _tmp: String? = null
var tmp: String
get() = _tmp!!
set(value) {_tmp=value; println("tmp set to $value")}
或者,如果您希望它与lateinit
语义保持一致,也可以采用这种方式:
private var _tmp: String? = null
var tmp: String
get() = _tmp ?: throw UninitializedPropertyAccessException("\"tmp\" was queried before being initialized")
set(value) {_tmp=value; println("tmp set to $value")}
这可以通过使用a(根据Pavlus的回答)来实现;但是,我更喜欢将其包装在中,以避免将其暴露在属性上下文之外:
open class LateInit<T: Any> : ReadWriteProperty<Any?, T> {
protected lateinit var field: T
final override fun getValue(thisRef: Any?, property: KProperty<*>) = get()
final override fun setValue(thisRef: Any?, property: KProperty<*>, value: T) = set(value)
open fun get() = field
open fun set(value: T) { field = value }
}
我意识到,您还可以将您的私有财产
lateinit
设置为空,而不是将其设置为空:
var tmp: T
get() = _tmp
set(value) {
_tmp = value
println("tmp set to $value")
}
private lateinit var _tmp: T
onCreate
是构建器的一部分吗?不,它是继承自类活动的重写方法,在应用程序的生命周期中由Android调用。你为什么需要setter?听起来你可以在这里改进你的架构。我的setter更新了两个UI小部件。我想我不用塞特也能做到。但这是我以前多次面对的情况。所以我希望有一个简单的解决办法。我还发现属性是我在Java中错过的最酷的特性之一。你能添加一个例子吗?getter是如何工作的?您是否将值存储在支持字段中?这听起来像是您的一个特殊用例。但我仍然收到一个错误,因为我必须初始化我的属性。因此,您希望在Kotlin中使用未初始化的属性,但不希望它为null或引发异常?我尝试应用您的高级解决方案。但是我得到一个错误,因为tmp
没有初始化。你初始化了它?好的,我搞错了。我尝试了field=value
而不是\u tmp=value
。现在工作!
class LateInit<T: Any>(private val getter: FieldHolder<T>.() -> T = { field },
private val setter: FieldHolder<T>.(T) -> Unit = { field = it }) :
ReadWriteProperty<Any?, T> {
private val fieldHolder = FieldHolder<T>()
override fun getValue(thisRef: Any?, property: KProperty<*>) = fieldHolder.getter()
override fun setValue(thisRef: Any?, property: KProperty<*>, value: T) =
fieldHolder.setter(value)
class FieldHolder<T: Any> {
lateinit var field: T
}
}
private var upperCaseString: String by LateInit(setter = { field = it.toUpperCase() })
var tmp: T
get() = _tmp
set(value) {
_tmp = value
println("tmp set to $value")
}
private lateinit var _tmp: T