1.委托是什么?
1.1 官网示例
在每个变量委托的实现的背后,Kotlin 编译器都会生成辅助对象并委托给它。 假设委托如下,
1 class C { 2 var prop: Type by MyDelegate() 3 } 4
那么编译器生成的相应代码如下:
1 class C { 2 private val prop$delegate = MyDelegate() 3 var prop: Type 4 get() = prop$delegate.getValue(this, this::prop) 5 set(value: Type) = prop$delegate.setValue(this, this::prop, value) 6 }
其中:
- val prop$delegate 就是被委托的对象
- getValue与setValue就是对prop的管理函数
1.2 变量委托是一系列类
变量委托是重载setValue,getValue运算符的类,可直接重载或者实现ReadWriteProperty、ReadOnlyProperty 接口之一。
1 operator fun getValue(thisRef: R, property: KProperty<*>): T 2 operator fun setValue(thisRef: R, property: KProperty<*>, value: T)
其中
thisRef
—— 必须与委托都类型相同或者是它的超类型;property
—— 必须是类型KProperty<*>
或其超类型。- value 必须与委托者同类型或者是它的子类型
- 返回值与委托者相同类型(或其子类型)
下面看下lazy是怎么实现的
1 val i11 by lazy { 1 }
点开lazy的实现
/** * Creates a new instance of the [Lazy] that uses the specified initialization function [initializer] * and the default thread-safety mode [LazyThreadSafetyMode.SYNCHRONIZED]. * * If the initialization of a value throws an exception, it will attempt to reinitialize the value at next access. * * Note that the returned instance uses itself to synchronize on. Do not synchronize from external code on * the returned instance as it may cause accidental deadlock. Also this behavior can be changed in the future. */ public actual fun <T> lazy(initializer: () -> T): Lazy<T> = SynchronizedLazyImpl(initializer)
lazy是个函数 ,返回Lazy<T> ,再看下Lazy
1 /** 2 * Represents a value with lazy initialization. 3 * 4 * To create an instance of [Lazy] use the [lazy] function. 5 */ 6 public interface Lazy<out T> { 7 /** 8 * Gets the lazily initialized value of the current Lazy instance. 9 * Once the value was initialized it must not change during the rest of lifetime of this Lazy instance. 10 */ 11 public val value: T 12 13 /** 14 * Returns `true` if a value for this Lazy instance has been already initialized, and `false` otherwise. 15 * Once this function has returned `true` it stays `true` for the rest of lifetime of this Lazy instance. 16 */ 17 public fun isInitialized(): Boolean 18 }
并没有operator getValue,往下看
1 /** 2 * An extension to delegate a read-only property of type [T] to an instance of [Lazy]. 3 * 4 * This extension allows to use instances of Lazy for property delegation: 5 * `val property: String by lazy { initializer }` 6 */ 7 @kotlin.internal.InlineOnly 8 public inline operator fun <T> Lazy<T>.getValue(thisRef: Any?, property: KProperty<*>): T = value
原来它是扩展重载的getValue运算符。
再看下Delegates.observable,它返回的 ObservableProperty 实现了 ReadWriteProperty 接口。
1 /** 2 * Returns a property delegate for a read/write property that calls a specified callback function when changed. 3 * @param initialValue the initial value of the property. 4 * @param onChange the callback which is called after the change of the property is made. The value of the property 5 * has already been changed when this callback is invoked. 6 * 7 * @sample samples.properties.Delegates.observableDelegate 8 */ 9 public inline fun <T> observable(initialValue: T, crossinline onChange: (property: KProperty<*>, oldValue: T, newValue: T) -> Unit): 10 ReadWriteProperty<Any?, T> = 11 object : ObservableProperty<T>(initialValue) { 12 override fun afterChange(property: KProperty<*>, oldValue: T, newValue: T) = onChange(property, oldValue, newValue) 13 }
1 public abstract class ObservableProperty<T>(initialValue: T) : ReadWriteProperty<Any?, T> { 2 3 //... 4 public override fun getValue(thisRef: Any?, property: KProperty<*>): T { 5 return value 6 } 7 8 public override fun setValue(thisRef: Any?, property: KProperty<*>, value: T) { 9 val oldValue = this.value 10 if (!beforeChange(property, oldValue, value)) { 11 return 12 } 13 this.value = value 14 afterChange(property, oldValue, value) 15 } 16 }
2.by后面的是什么?
by后面的是委托类的一个对象
示例代码
1 class lazy11(var default : Int = -1,var lmda : () -> Int) { 2 operator fun provideDelegate( thisRef : Any,prop : KProperty<*>) : Delegate13 { 3 return Delegate13(lmda) 4 } 5 } 6 7 val i11 by lazy { 1 } 8 9 class D11{ 10 val MAX by lazy { 1024 } 11 12 var lazy = lazy{ 9 } 13 val value : Int by lazy 14 15 var lazy11 = lazy11{8} 16 var count : Int by lazy11 17 } 18 19 fun delegate_test11(){ 20 Log.e(TAG_DELEGATE,"====================================== delegate_test_11 ") 21 22 var d11 = D11() 23 Log.e(TAG_DELEGATE,"d11.value = ${d11.value},d11.count = ${d11.count} ,d11.MAX = ${d11.MAX}") 24 }
结果
2019-09-13 16:54:51.742 10374-10374/com.example.kotlin E/delegate: ====================================== delegate_test_11
2019-09-13 16:54:51.744 10374-10374/com.example.kotlin E/delegate: Delegate13.getValue
2019-09-13 16:54:51.744 10374-10374/com.example.kotlin E/delegate: d11.value = 9,d11.count = 8 ,d11.MAX = 1024
其中:MAX委托的是编译器生成的对象,而value与count则是直接托委的成员对象。
3.自定义变量委托
3.1 直接重载getValue,setValue运算符
1 class BYY{ 2 var value : Int = -1 3 4 operator fun setValue(thisRef: Any, property: KProperty<*>, v : Int) { 5 Log.e(TAG_DELEGATE,"BYY.setValue") 6 value = v 7 } 8 operator fun getValue(thisRef: Any, property: KProperty<*>): Int { 9 Log.e(TAG_DELEGATE,"BYY.getValue") 10 return value 11 } 12 } 13 operator fun BYY.setValue(thisRef: Nothing?, property: KProperty<*>, v : Int){ 14 15 } 16 operator fun BYY.get(thisRef: Nothing?, property: KProperty<*>) = value 17 18 class D12{ 19 var size : Int by BYY() 20 } 21 22 fun delegate_test12(){ 23 Log.e(TAG_DELEGATE,"====================================== delegate_test_12 ") 24 var d12 = D12() 25 d12.size = 128 26 Log.e(TAG_DELEGATE,"d12.size = ${d12.size}") 27 28 }
结果
2019-09-13 17:02:43.564 10695-10695/com.example.kotlin E/delegate: ====================================== delegate_test_12
2019-09-13 17:02:43.564 10695-10695/com.example.kotlin E/delegate: BYY.setValue
2019-09-13 17:02:43.564 10695-10695/com.example.kotlin E/delegate: BYY.getValue
2019-09-13 17:02:43.564 10695-10695/com.example.kotlin E/delegate: d12.size = 128
3.2 实现 委托接口
ReadOnlyProperty 与 ReadWriteProperty 这两个接口声明了getValue,setValue两个运算符,
1 class MyDelegate() : ReadOnlyProperty<DC12,Int>,ReadWriteProperty<DC12,Int>{ 2 var value : Int = 0 3 override fun setValue(thisRef: DC12, property: KProperty<*>, v : Int) { 4 Log.e(TAG_DELEGATE,"MyDelegate.setValue ") 5 value = v 6 } 7 8 override fun getValue(thisRef: DC12, property: KProperty<*>) : Int { 9 Log.e(TAG_DELEGATE,"MyDelegate.setValue ") 10 return value 11 } 12 constructor(lmda : ()-> Int) : this (){ 13 value = lmda() 14 } 15 } 16 fun getNum() : Int{ 17 Log.e(TAG_DELEGATE,"getNum ") 18 return 33 19 } 20 21 class DC12{ 22 var value : Int by MyDelegate() 23 var value2 : Int by MyDelegate(::getNum) 24 } 25 26 fun delegate_test12(){ 27 Log.e(TAG_DELEGATE,"====================================== delegate_test_12 ") 28 29 var dc12 = DC12() 30 dc12.value = 64 31 Log.e(TAG_DELEGATE,"dc12.value = ${dc12.value},dc12.value2 = ${dc12.value2}") 32 }
结果
2019-09-13 17:04:07.213 10931-10931/com.example.kotlin E/delegate: ====================================== delegate_test_12
2019-09-13 17:04:07.214 10931-10931/com.example.kotlin E/delegate: getNum
2019-09-13 17:04:07.214 10931-10931/com.example.kotlin E/delegate: MyDelegate.setValue
2019-09-13 17:04:07.214 10931-10931/com.example.kotlin E/delegate: MyDelegate.setValue
2019-09-13 17:04:07.214 10931-10931/com.example.kotlin E/delegate: MyDelegate.setValue
2019-09-13 17:04:07.214 10931-10931/com.example.kotlin E/delegate: dc12.value = 64,dc12.value2 = 33
3.3 委托提供运算符 provideDelegate
如果 by 右侧所使用的对象将 provideDelegate 定义为成员或扩展函数,那么会调用该函数来创建属性委托实例。
1 class Delegate13 (lmda: () -> Int) : ReadOnlyProperty<Any,Int>,ReadWriteProperty<Any,Int>{ 2 var COUNT : Int 3 init{ 4 COUNT = lmda() 5 } 6 override fun setValue(thisRef: Any, property: KProperty<*>, value: Int) { 7 Log.e(TAG_DELEGATE,"Delegate13.setValue") 8 COUNT = value 9 } 10 override fun getValue(thisRef: Any, property: KProperty<*>): Int { 11 Log.e(TAG_DELEGATE,"Delegate13.getValue") 12 return COUNT 13 } 14 } 15 class mutableLazy(var default : Int = -1,var lmda : () -> Int) { 16 operator fun provideDelegate( thisRef : Any,prop : KProperty<*>) : Delegate13 { 17 return Delegate13(lmda) 18 } 19 } 20 21 class D13{ 22 var value : Int by mutableLazy{ 23 Log.e(TAG_DELEGATE,"mutableLazy.lmda") 24 99 25 } 26 } 27 28 fun delegate_test13(){ 29 Log.e(TAG_DELEGATE,"====================================== delegate_test_13 ") 30 31 var d13 = D13() 32 Log.e(TAG_DELEGATE,"d13.value = ${d13.value}") 33 34 d13.value = 299 35 Log.e(TAG_DELEGATE,"d13.value = ${d13.value}") 36 }
结果
2019-09-13 20:52:31.350 25146-25146/com.example.kotlin E/delegate: ====================================== delegate_test_13
2019-09-13 20:52:31.350 25146-25146/com.example.kotlin E/delegate: mutableLazy.lmda
2019-09-13 20:52:31.350 25146-25146/com.example.kotlin E/delegate: Delegate13.getValue
2019-09-13 20:52:31.350 25146-25146/com.example.kotlin E/delegate: d13.value = 99
2019-09-13 20:52:31.350 25146-25146/com.example.kotlin E/delegate: Delegate13.setValue
2019-09-13 20:52:31.350 25146-25146/com.example.kotlin E/delegate: Delegate13.getValue
2019-09-13 20:52:31.351 25146-25146/com.example.kotlin E/delegate: d13.value = 299