Kotlin 之代理 Delegate

代理关键字 by

属性代理:对象X代替属性a实现getter、setter方法。

接口代理:对象X代替类B实现接口C的方法。

举例

属性代理

在UI初始中使用过,代码如下:

 1 class MainActivity : AppCompatActivity() {
 2 
 3     private val mTvName: TextView by lazy {
 4         findViewById(R.id.name)
 5     }
 6 
 7     override fun onCreate(savedInstanceState: Bundle?) {
 8         super.onCreate(savedInstanceState)
 9         setContentView(R.layout.activity_main)
10     }
11 }

接口lazy的实例代理了对象MainActivity实例的属性mTvName的getter方法。

lazy是一个Lambda函数,lazy实现:

  1 /**
  2  * Creates a new instance of the [Lazy] that uses the specified initialization function [initializer]
  3  * and the default thread-safety mode [LazyThreadSafetyMode.SYNCHRONIZED].
  4  *
  5  * If the initialization of a value throws an exception, it will attempt to reinitialize the value at next access.
  6  *
  7  * Note that the returned instance uses itself to synchronize on. Do not synchronize from external code on
  8  * the returned instance as it may cause accidental deadlock. Also this behavior can be changed in the future.
  9  */
 10 public actual fun <T> lazy(initializer: () -> T): Lazy<T> = SynchronizedLazyImpl(initializer)
 11 
 12 /**
 13  * Creates a new instance of the [Lazy] that uses the specified initialization function [initializer]
 14  * and thread-safety [mode].
 15  *
 16  * If the initialization of a value throws an exception, it will attempt to reinitialize the value at next access.
 17  *
 18  * Note that when the [LazyThreadSafetyMode.SYNCHRONIZED] mode is specified the returned instance uses itself
 19  * to synchronize on. Do not synchronize from external code on the returned instance as it may cause accidental deadlock.
 20  * Also this behavior can be changed in the future.
 21  */
 22 public actual fun <T> lazy(mode: LazyThreadSafetyMode, initializer: () -> T): Lazy<T> =
 23     when (mode) {
 24         LazyThreadSafetyMode.SYNCHRONIZED -> SynchronizedLazyImpl(initializer)
 25         LazyThreadSafetyMode.PUBLICATION -> SafePublicationLazyImpl(initializer)
 26         LazyThreadSafetyMode.NONE -> UnsafeLazyImpl(initializer)
 27     }
 28 
 29 /**
 30  * Creates a new instance of the [Lazy] that uses the specified initialization function [initializer]
 31  * and the default thread-safety mode [LazyThreadSafetyMode.SYNCHRONIZED].
 32  *
 33  * If the initialization of a value throws an exception, it will attempt to reinitialize the value at next access.
 34  *
 35  * The returned instance uses the specified [lock] object to synchronize on.
 36  * When the [lock] is not specified the instance uses itself to synchronize on,
 37  * in this case do not synchronize from external code on the returned instance as it may cause accidental deadlock.
 38  * Also this behavior can be changed in the future.
 39  */
 40 public actual fun <T> lazy(lock: Any?, initializer: () -> T): Lazy<T> = SynchronizedLazyImpl(initializer, lock)
 41 
 42 
 43 
 44 private class SynchronizedLazyImpl<out T>(initializer: () -> T, lock: Any? = null) : Lazy<T>, Serializable {
 45     private var initializer: (() -> T)? = initializer
 46     @Volatile private var _value: Any? = UNINITIALIZED_VALUE
 47     // final field is required to enable safe publication of constructed instance
 48     private val lock = lock ?: this
 49 
 50     override val value: T
 51         get() {
 52             val _v1 = _value
 53             if (_v1 !== UNINITIALIZED_VALUE) {
 54                 @Suppress("UNCHECKED_CAST")
 55                 return _v1 as T
 56             }
 57 
 58             return synchronized(lock) {
 59                 val _v2 = _value
 60                 if (_v2 !== UNINITIALIZED_VALUE) {
 61                     @Suppress("UNCHECKED_CAST") (_v2 as T)
 62                 } else {
 63                     val typedValue = initializer!!()
 64                     _value = typedValue
 65                     initializer = null
 66                     typedValue
 67                 }
 68             }
 69         }
 70 
 71     override fun isInitialized(): Boolean = _value !== UNINITIALIZED_VALUE
 72 
 73     override fun toString(): String = if (isInitialized()) value.toString() else "Lazy value not initialized yet."
 74 
 75     private fun writeReplace(): Any = InitializedLazyImpl(value)
 76 }
 77 
 78 
 79 private class SafePublicationLazyImpl<out T>(initializer: () -> T) : Lazy<T>, Serializable {
 80     @Volatile private var initializer: (() -> T)? = initializer
 81     @Volatile private var _value: Any? = UNINITIALIZED_VALUE
 82     // this final field is required to enable safe initialization of the constructed instance
 83     private val final: Any = UNINITIALIZED_VALUE
 84 
 85     override val value: T
 86         get() {
 87             val value = _value
 88             if (value !== UNINITIALIZED_VALUE) {
 89                 @Suppress("UNCHECKED_CAST")
 90                 return value as T
 91             }
 92 
 93             val initializerValue = initializer
 94             // if we see null in initializer here, it means that the value is already set by another thread
 95             if (initializerValue != null) {
 96                 val newValue = initializerValue()
 97                 if (valueUpdater.compareAndSet(this, UNINITIALIZED_VALUE, newValue)) {
 98                     initializer = null
 99                     return newValue
100                 }
101             }
102             @Suppress("UNCHECKED_CAST")
103             return _value as T
104         }
105 
106     override fun isInitialized(): Boolean = _value !== UNINITIALIZED_VALUE
107 
108     override fun toString(): String = if (isInitialized()) value.toString() else "Lazy value not initialized yet."
109 
110     private fun writeReplace(): Any = InitializedLazyImpl(value)
111 
112     companion object {
113         private val valueUpdater = java.util.concurrent.atomic.AtomicReferenceFieldUpdater.newUpdater(
114             SafePublicationLazyImpl::class.java,
115             Any::class.java,
116             "_value"
117         )
118     }
119 }

当然能代理getter方法就能代理setter方法,上代码:

class Person() {

    private var mName: String by Delegates.observable("") {
        property, oldValue, newValue ->
        println("name setter old value: $oldValue to new value: $newValue")
    }
    
}

源码实现:

 1 /**
 2  * Standard property delegates.
 3  */
 4 public object Delegates {
 5     /**
 6      * Returns a property delegate for a read/write property with a non-`null` value that is initialized not during
 7      * object construction time but at a later time. Trying to read the property before the initial value has been
 8      * assigned results in an exception.
 9      *
10      * @sample samples.properties.Delegates.notNullDelegate
11      */
12     public fun <T : Any> notNull(): ReadWriteProperty<Any?, T> = NotNullVar()
13 
14     /**
15      * Returns a property delegate for a read/write property that calls a specified callback function when changed.
16      * @param initialValue the initial value of the property.
17      * @param onChange the callback which is called after the change of the property is made. The value of the property
18      *  has already been changed when this callback is invoked.
19      *
20      *  @sample samples.properties.Delegates.observableDelegate
21      */
22     public inline fun <T> observable(initialValue: T, crossinline onChange: (property: KProperty<*>, oldValue: T, newValue: T) -> Unit):
23             ReadWriteProperty<Any?, T> =
24         object : ObservableProperty<T>(initialValue) {
25             override fun afterChange(property: KProperty<*>, oldValue: T, newValue: T) = onChange(property, oldValue, newValue)
26         }
27 
28     /**
29      * Returns a property delegate for a read/write property that calls a specified callback function when changed,
30      * allowing the callback to veto the modification.
31      * @param initialValue the initial value of the property.
32      * @param onChange the callback which is called before a change to the property value is attempted.
33      *  The value of the property hasn't been changed yet, when this callback is invoked.
34      *  If the callback returns `true` the value of the property is being set to the new value,
35      *  and if the callback returns `false` the new value is discarded and the property remains its old value.
36      *
37      *  @sample samples.properties.Delegates.vetoableDelegate
38      *  @sample samples.properties.Delegates.throwVetoableDelegate
39      */
40     public inline fun <T> vetoable(initialValue: T, crossinline onChange: (property: KProperty<*>, oldValue: T, newValue: T) -> Boolean):
41             ReadWriteProperty<Any?, T> =
42         object : ObservableProperty<T>(initialValue) {
43             override fun beforeChange(property: KProperty<*>, oldValue: T, newValue: T): Boolean = onChange(property, oldValue, newValue)
44         }
45 
46 }

 属性代理最重要的接口类源码:

 1 /**
 2  * Base interface that can be used for implementing property delegates of read-write properties.
 3  *
 4  * This is provided only for convenience; you don't have to extend this interface
 5  * as long as your property delegate has methods with the same signatures.
 6  *
 7  * @param R the type of object which owns the delegated property.
 8  * @param T the type of the property value.
 9  */
10 public interface ReadWriteProperty<in R, T> {
11     /**
12      * Returns the value of the property for the given object.
13      * @param thisRef the object for which the value is requested.
14      * @param property the metadata for the property.
15      * @return the property value.
16      */
17     public operator fun getValue(thisRef: R, property: KProperty<*>): T
18 
19     /**
20      * Sets the value of the property for the given object.
21      * @param thisRef the object for which the value is requested.
22      * @param property the metadata for the property.
23      * @param value the value to set.
24      */
25     public operator fun setValue(thisRef: R, property: KProperty<*>, value: T)
26 }

其实,我们也可以实现类似接口,通过operator操作符:

 1 class Foo() {
 2     val x: Int by Person()
 3 
 4     var y: Int by Person()
 5 }
 6 
 7 class Person() {
 8 
 9     private var value: Int? = null
10 
11     operator fun getValue(thisRef: Any?, property: KProperty<*>): Int {
12         return value ?: throw IllegalStateException("Property ${property.name} should be initialized before get.")
13     }
14 
15     operator fun setValue(thisRef: Any?, property: KProperty<*>, value: Int) {
16         this.value = value
17     }
18 
19 }

接口代理

未使用代理 by :

 1 interface IApi {
 2     fun methodA()
 3     fun methodB()
 4     fun methodC()
 5 }
 6 
 7 class Person(private val api: IApi): IApi {
 8     
 9     override fun methodA() {
10         api.methodA()
11     }
12 
13     override fun methodB() {
14         api.methodB()
15     }
16 
17     override fun methodC() {
18         api.methodC()
19     }
20 
21 }

使用代理 by :

 1 interface IApi {
 2     fun methodA()
 3     fun methodB()
 4     fun methodC()
 5 }
 6 
 7 class Person(private val api: IApi) : IApi by api {
 8     // 对象api代替类Person实现接口IApi方法
 9     override fun methodC() {
10         TODO("Not yet implemented")
11     }
12 }
原文地址:https://www.cnblogs.com/naray/p/12992952.html