美文网首页技术干货All Kotlin For U
Kotlin Common篇之 二 AutoClearedVal

Kotlin Common篇之 二 AutoClearedVal

作者: super_shanks | 来源:发表于2019-05-16 10:03 被阅读16次

    首发于公众号: DSGtalk1989

    自动清理代理类,会跟随着组件的生命周期,当组件被回收时会自我置null,这里需要用到kotlin的属性代理知识,以及lifecycle组件。

    这里不像SP代理那样需要我们在取值和赋值时做一些额外的操作。就想上面所说是在固定的生命周期做一些回收用的。

    我们先来一个随便的属性代理。

    class AutoClearedValue<T : Any?> : ReadWriteProperty<Any, T?> {
          private var _value: T? = null
      
          override fun getValue(thisRef: Any, property: KProperty<*>): T? {
              return _value
          }
      
          override fun setValue(thisRef: Any, property: KProperty<*>, value: T?) {
              _value = value
          }
      }
    

    可以代理任何类的任何属性,返回结果可以为空。

    OK,现在我们希望在代理属性所在类的生命周期结束的时候回收这个代理属性的做法如下:

    fragment.lifecycle.addObserver(object : LifecycleObserver {
          @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
          fun onDestroy() {
              _value = null
          }
    })
    

    通过lifecycle框架的addObserver方法添加生命周期回调监听,当被回收时,代理属性置空,这个方法我们直接在代理类初始化的过程中做即可。所以我们代理的类指定为Fragment

    class AutoClearedValue<T : Any?>(val fragment: Fragment) : ReadWriteProperty<Fragment, T?> {
          private var _value: T? = null
      
          init {
              fragment.lifecycle.addObserver(object : LifecycleObserver {
                  @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
                  fun onDestroy() {
                      _value = null
                  }
              })
          }
      
          override fun getValue(thisRef: Fragment, property: KProperty<*>): T? {
              return _value
          }
      
          override fun setValue(thisRef: Fragment, property: KProperty<*>, value: T?) {
              _value = value
          }
      }
    

    本身作为内容到这里为止就好,但是当你发现,你在Fragment中进行属性代理的过程中出现了Warning

    private var normalAdapterManager by AutoClearedValue<BindingDataRecyclerManager>(this)
    

    最终的this下面有根黄线,报可能会存在泄漏的问题。我们在构造函数中直接传入了非final的类Fragment。也就是说针对可能会存在泄漏的类,我们不适合放在构造函数中让外面传进来,或者说,我们可以使用更好的方式。

    kotlin大神就建议我们这么做https://github.com/bluelinelabs/Conductor/issues/234#issuecomment-322116408),即通过拓展方法实现横向补充。

    fun <T : Any?> Fragment.autoCleared() = AutoClearedValue<T?>(this)
    

    直接在Fragment类中生成一个新的方法autoCleared可以生成一个针对任何类型属性的代理。

    所以上面提示warning的我们只需要改成如下即可。

    private var normalAdapterManager by autoCleared<BindingDataRecyclerManager>()
    

    这样一来,所有在fragment内通过autoCleared方法代理的属性都可以完美的避免泄漏问题。一旦fragment回收,它们就会自动销毁。

    相关文章

      网友评论

        本文标题:Kotlin Common篇之 二 AutoClearedVal

        本文链接:https://www.haomeiwen.com/subject/tijbaqtx.html