Kotlin 的委派 ReadWriteProperty 和 ReadOnlyProperty 简单使用

Kotlin 的委派 ReadWriteProperty 和 ReadOnlyProperty 简单使用,第1张

Kotlin 的委派 ReadWriteProperty 和 ReadOnlyProperty 简单使用

案例1–自定义ReadWriteProperty,实现Activity/Fragment 成员变量自动回收

案例2–自定义ReadOnlyProperty,实现Activity/Fragment 辅助创建ViewBinding以及自动回收内存

  1. 先看下ReadWriteProperty 和 ReadOnlyProperty 的源码,源码很简单,就是两个接口。ReadOnlyProperty 有一个getValue方法,ReadWriteProperty 继承了 ReadOnlyProperty ,同时增加了一个setValue方法。

/**
 * Base interface that can be used for implementing property delegates of read-only properties.
 *
 * This is provided only for convenience; you don't have to extend this interface
 * as long as your property delegate has methods with the same signatures.
 *
 * @param T the type of object which owns the delegated property.
 * @param V the type of the property value.
 */
public fun interface ReadOnlyProperty<in T, out 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 operator fun getValue(thisRef: T, property: KProperty<*>): V
}

/**
 * Base interface that can be used for implementing property delegates of read-write properties.
 *
 * This is provided only for convenience; you don't have to extend this interface
 * as long as your property delegate has methods with the same signatures.
 *
 * @param T the type of object which owns the delegated property.
 * @param V the type of the property value.
 */
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)
}

  1. 现在直接看下 kotlin 的三个委派的实现方法,看一眼,过。

/**
 * Standard property delegates.
 */
public object Delegates {
    /**
     * Returns a property delegate for a read/write property with a non-`null` value that is initialized not during
     * object construction time but at a later time. Trying to read the property before the initial value has been
     * assigned results in an exception.
     *
     * @sample samples.properties.Delegates.notNullDelegate
     */
    public fun <T : Any> notNull(): ReadWriteProperty<Any?, T> = NotNullVar()

    /**
     * Returns a property delegate for a read/write property that calls a specified callback function when changed.
     * @param initialValue the initial value of the property.
     * @param 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.
     *
     *  @sample samples.properties.Delegates.observableDelegate
     */
    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)
        }

    /**
     * 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)
        }

}
  1. 接下来 直接说下这三个方法的使用

Delegates.notNull() 直接看注释:

class MainActivity : AppCompatActivity() {

    // 稍后初始化值
    //类似 lateinit var isInit: Any
    //但是 lateinit var 不可以修饰 Float、Long、Int、Boolean这些在java中的基本类型
    //不要用val 修饰,不然没意义
    private var isInit by Delegates.notNull<Boolean>()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        isInit = true
        Log.e("MainActivity", "isInit::$isInit")
    }
}

Delegates.observable(),监听值得改变, 场景想到是数据驱动UI,当数据发生改变的时候,去更新UI界面。

class MainActivity : AppCompatActivity() {

    /**
     * 监听name的变化,
     * oldValue 是上一次的值,
     * newValue 更改后的值
     */
    private var name by Delegates.observable<String>("xiao li") { _, oldValue, newValue ->
        Log.e("MainActivity", "name updated oldValue::$oldValue, newValue::$newValue")
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        name = "wang"
        Log.e("MainActivity", "name::$name")
    }
}
//打印的结果
//E/MainActivity: name updated oldValue::xiao li, newValue::wang
//E/MainActivity: name::wang

Delegates.vetoable(),同样是监听值得变化,不过这个方法增加判断,由用户决定是否修改值

class MainActivity : AppCompatActivity() {

    /**
     * 监听 data的值修改之前
     * 返回false,意思抛弃newValue的值,不做修改
     * 返回true,做修改
     */
    private var data by Delegates.vetoable<Int>(0) { _, oldValue, newValue ->
        // 新的值 小于5 才做修改
        newValue < 5
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        for (i in 0 until 8) {
            data = i
            Log.e("MainActivity", "for i::$i data::$data")
        }
    }
}
//打印结果:
 E/MainActivity: for i::0 data::0
 E/MainActivity: for i::1 data::1
 E/MainActivity: for i::2 data::2
 E/MainActivity: for i::3 data::3
 E/MainActivity: for i::4 data::4
 E/MainActivity: for i::5 data::4
 E/MainActivity: for i::6 data::4
 E/MainActivity: for i::7 data::4

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/876391.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-13
下一篇 2022-05-13

发表评论

登录后才能评论

评论列表(0条)

保存