我的目标:我有一个简单的公共类
val reds = IntArray(10)
val greens = IntArray(10)
val blues = IntArray(10)
val lums = IntArray(10)
如果有人修改任何红色值,我想更新 lum 值。
myObj.reds[5] = 100 // Should update myObj.lums[5] = reds[5]+greens[5]+blues[5]
问题是by Delegates.observable
似乎只用于 var 对象 - 没有提到"如果你修改数组的元素,这就是触发的内容">
也许这是不可能的,我必须通过 getter 和 setter 进行所有修改 - 但我宁愿有类似可观察的触发器!
你将不得不使用自定义类,IntArray
映射到原始int[]
数组,所以它不提供任何注入回调的地方 - 像你的示例一样更改值 (myObj.reds[5] = 100
( 你只知道数组何时返回,但无法控制之后的更改。
例如,您可以创建如下类:
class IntArrayWrapper(size: Int,
val setterObs : ((index: Int, value: Int) -> Unit)? = null){
val field = IntArray(size)
val size
get() = field.size
operator fun iterator() = field.iterator()
operator fun get(i: Int) : Int {
return field[i]
}
operator fun set(i: Int, value: Int){
field[i] = value
setterObs?.invoke(i, value)
}
}
运算符函数将允许您使用与直接访问它相同的语法从基础数组中获取值。 构造函数中的setterObs
参数允许您传递 setter 方法的"观察者":
val reds = IntArrayWrapper(10){index, value ->
println("$index changed to $value")
invalidateLums(index) // method that modifies lums or whatever you need
}
val a = reds[2] // getter usage
reds[3] = 5 // setter usage that triggers the setter observer callback
reds.field[4] = 3 // set value in backing array directly, allows modification without setter callback
请注意,这会带来限制,因为您将无法在不引用支持field
的情况下自由使用IntArray
扩展方法,也无法将此类作为Array
参数传递。
我不知道这是否是解决问题的最干净方法,但是,您可以使用ObservableList
(FX可观察集合(:
var numbers: ObservableList<Int> = FXCollections.observableArrayList()
numbers.addListener(ListChangeListener<Int> {
//Do things on change
})
但正如我所提到的,通过添加这些集合,您将 FX 组件混合到您的应用程序中,我不知道它是否需要,甚至它是否适用于 android 等各种平台!