Kotlin-可观测属性委托(Observable)-Delegates.observable Delegates.vetoable
委托属性在实际开发中是有如下4种使用情况的
1、延迟属性。
2、可观测属性。
3、非空属性。
4、map属性。
可观测属性委托(Observable)
public inline fun <T> observable(initialValue: T, crossinline onChange: (property: KProperty<*>, oldValue: T, newValue: T) -> Unit):
ReadWriteProperty<Any?, T> =
object : ObservableProperty<T>(initialValue) {
override fun afterChange(property: KProperty<*>, oldValue: T, newValue: T) = onChange(property, oldValue, newValue)
定义一个这个可观测的属性委托:
class Person {
var age: Int by Delegates.observable(20) {
prop, oldValue, newValue -> println("${prop.name}, oldValue: $oldValue, newValue: $newValue")
}
}
来调用一下:
fun main(args: Array<String>) {
val person = Person()
person.age = 30
person.age = 40
}
RUN> ???????♀️?♀️?♀️
age, oldValue: 20, newValue: 30 age, oldValue: 30, newValue: 40
可以追踪值得变化
读一读它的javadoc的说明:
Returns a property delegate for a read/write property that calls a specified callback function when changed.
Params:
initialValue - the initial value of the property.
onChange - the callback which is called after the change of the property is made. The value of the property has already been changed when this callback is invoked.
Samples:
samples.properties.Delegates.observableDelegate
返回针对读写属性的一个代理,该代表会在值发生改变时去调用指定的回调函数
该回调是当属性的改变发生进行调用的。当该回调函数被调用也就意味着该属性的值已经发生改变了
public interface ReadWriteProperty<in T, V> : ReadOnlyProperty<T, V> {
/**
* Returns the value of the property for the given object.
* @param thisRef the object for which the value is requested.
* @param property the metadata for the property.
* @return the property value.
*/
public override operator fun getValue(thisRef: T, property: KProperty<*>): V
/**
* Sets the value of the property for the given object.
* @param thisRef the object for which the value is requested.
* @param property the metadata for the property.
* @param value the value to set.
*/
public operator fun setValue(thisRef: T, property: KProperty<*>, value: V)
}
该基类接口能够被用于实现只读属性的属性委托。
它只是为了提示一个便利:你并不需要继承这个接口,只要你的属性委托拥有相同签名的方法既可。
对于这个observable方法是监听值改变之后的结果,那有没有能监听值改变之前做点东东的么?答案是有的,就是紧挨着observable()方法下面这个:
/**
* Returns a property delegate for a read/write property that calls a specified callback function when changed,
* allowing the callback to veto the modification.
* @param initialValue the initial value of the property.
* @param onChange the callback which is called before a change to the property value is attempted.
* The value of the property hasn't been changed yet, when this callback is invoked.
* If the callback returns `true` the value of the property is being set to the new value,
* and if the callback returns `false` the new value is discarded and the property remains its old value.
*
* @sample samples.properties.Delegates.vetoableDelegate
* @sample samples.properties.Delegates.throwVetoableDelegate
*/
public inline fun <T> vetoable(initialValue: T, crossinline onChange: (property: KProperty<*>, oldValue: T, newValue: T) -> Boolean):
ReadWriteProperty<Any?, T> =
object : ObservableProperty<T>(initialValue) {
override fun beforeChange(property: KProperty<*>, oldValue: T, newValue: T): Boolean = onChange(property, oldValue, newValue)
}
返回针对读写属性的一个属性委托,当属性发生变化时会调用指定的回调函数,并且允许该回调来否决这种修改
尝试着对属性的值进行修改之前该方法会被调用。当回调被调用时,该属性的值其实还未被修改。
如果这个回调返回true则属性的值就会被设置成新值,而如果该回调返回false则新的值就会被丢弃,并且属性会保持老的值。
下面来试一下该方法:
class Person2 {
var age: Int by Delegates.vetoable(20) {
prop, oldValue, newValue -> when {
oldValue <= newValue -> true
else -> false
}
}
}
fun main(args: Array<String>) {
val person2 = Person2()
println(person2.age)
person2.age = 40
println(person2.age)
println("========")
person2.age = 30
println(person2.age)
println("--------")
}
RUN > ???????????
20 40 ======== 40 --------
下面对其进行总结一下:
Delegates.observable接收两个参数:初始值与修改处理器。
处理器会在我们每次对属性赋值时得到调用(在赋值完成之后被调用),处理器本身接收3个参数:被赋值的属性本身,旧的属性值与新的属性值。
Delegates.vetoable的调用时机与Delegates.observable相反,它是在对属性赋值之前被调用,根据Delegates.vetoable的返回结果是true还是false,来决定是否真正对属性进行赋值。