案例1–自定义ReadWriteProperty,实现Activity/Fragment 成员变量自动回收
案例2–自定义ReadOnlyProperty,实现Activity/Fragment 辅助创建ViewBinding以及自动回收内存
- 先看下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)
}
- 现在直接看下 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)
}
}
- 接下来 直接说下这三个方法的使用
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
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
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)