Kotlin可reset的lazy加载托管的实现

文章介绍了Kotlin的lazy属性委托用于实现属性的懒加载,但其不适用于需要重置的情况。作者提出并实现了一个ResettableLazy类,该类在保持lazy的线程安全特性的基础上,增加了属性的重置功能,允许在需要时重新加载属性值。
摘要由CSDN通过智能技术生成

Kotlin的lazy属性委托可以实现对属性的懒加载,但是只能使用于不可变属性,当属性需要重新加载时即无法使用,编写了一个resettablelazy,在满足懒加载的同时,也能在适当时机对属性进行重置,让属性在重置后的下次调用重新加载

基本概念
by关键字在kotlin中称为属性委托,指将某个属性托付给一个代理类进行实现,这个属性的get和set方法由代理类的getValue()和setValue()方法
kotlin官方文档中的委托属性的相的模板:

import kotlin.reflect.KProperty

class Delegate {
    operator fun getValue(thisRef: Any?, property: KProperty<*>): String {
        return "$thisRef, thank you for delegating '${property.name}' to me!"
    }

    operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String) {
        println("$value has been assigned to '${property.name}' in $thisRef.")
    }
}

再进入kotlin的源码查看lazy的具体实现

public actual fun <T> lazy(initializer: () -> T): Lazy<T> = SynchronizedLazyImpl(initializer)
可以看到lazy返回了一个SynchronizedLazyImpl类的对象,进入SynchronizedLazyImpl:

private class SynchronizedLazyImpl<out T>(initializer: () -> T, lock: Any? = null) : Lazy<T>, Serializable {
    private var initializer: (() -> T)? = initializer
    @Volatile private var _value: Any? = UNINITIALIZED_VALUE
    // final field is required to enable safe publication of constructed instance
    private val lock = lock ?: this

    override val value: T
        get() {
            val _v1 = _value
            if (_v1 !== UNINITIALIZED_VALUE) {
                @Suppress("UNCHECKED_CAST")
                return _v1 as T
            }

            return synchronized(lock) {
                val _v2 = _value
                if (_v2 !== UNINITIALIZED_VALUE) {
                    @Suppress("UNCHECKED_CAST") (_v2 as T)
                } else {
                    val typedValue = initializer!!()
                    _value = typedValue
                    initializer = null
                    typedValue
                }
            }
        }

    override fun isInitialized(): Boolean = _value !== UNINITIALIZED_VALUE

    override fun toString(): String = if (isInitialized()) value.toString() else "Lazy value not initialized yet."

    private fun writeReplace(): Any = InitializedLazyImpl(value)
}

在SynchronizedLazyImpl中有一个不可变属性value,在value的get方法中通过判断保持返回对象的唯一性

结合使用lazy,即保持lazy的线程安全特性也保证了可重置
代码:

class ResettableLazy<PROPTYPE>(val init: () -> PROPTYPE) {

    var lazyHolder = makeInitBlock()

    operator fun getValue(thisRef: Any?, property: KProperty<*>): PROPTYPE {
        return lazyHolder.value
    }

    fun isInitialized(): Boolean {
        return lazyHolder.isInitialized()
    }

    fun reset() {
        lazyHolder = makeInitBlock()
    }

    fun makeInitBlock(): Lazy<PROPTYPE> {
        return lazy {
            init()
        }
    }
}

fun <PROPTYPE> resettableLazy(init: () -> PROPTYPE): ResettableLazy<PROPTYPE> {
    return ResettableLazy(init)
}

使用
使用时还是使用by
eg:

private val sdfLazy = resettableLazy {
   SimpleDateFormat.getDateTimeInstance(
           SimpleDateFormat.MEDIUM, SimpleDateFormat.SHORT, Locale.getDefault())
}
private val sdf: DateFormat by sdf1Lazy

重置调用调用托管类的reset方法:

sdf1Lazy.reset()
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值