LiveData去除粘性

class NoStickLiveData<T> : LiveData<T> {
    private var mVersion:Int

    //反射拿到父类的field mObservers。
    private var mObservers:(Iterable<MutableMap.MutableEntry<Observer<*>, *>>)? = null

    private fun requireMObservers() : Iterable<MutableMap.MutableEntry<Observer<*>, *>> {
        val mOb = mObservers
        if (mOb == null) {
            val ob = ReflectionUtils.iteratorGetPrivateFieldValue(this, "mObservers", true)
            val nob = ob as Iterable<MutableMap.MutableEntry<Observer<*>, *>>
            mObservers = nob
            return nob
        }
        return mOb
    }

    constructor() {
        mVersion = -1
    }
    constructor(data:T?) : super(data) {
        mVersion = 0
    }

    override fun setValue(value: T?) {
        mVersion++
        super.setValue(value)
    }

    
    /**
     * 追加不处理粘性的方式
     */
    fun observeUnStick(owner: LifecycleOwner, observer: Observer<in T>) {
        super.observe(owner, NoStickWrapObserver(this, observer = observer))
    }

    fun observeForeverUnStick(observer: Observer<in T>) {
        super.observeForever(NoStickWrapObserver(this, observer = observer))
    }

    fun removeObserverUnStick(observer: Observer<in T>) {
        val wrap = findObserverWrap(observer) ?: return
        super.removeObserver(wrap)
    }
    
    private fun findObserverWrap(observer: Observer<in T>) : Observer<in T>? {
        requireMObservers().let { iter->
            for ((key, _) in iter) {
                val wrap = key as NoStickWrapObserver<*>
                if (wrap.observer == observer) {
                    return wrap as Observer<in T>
                }
            }
        }
        return null
    }

    private class NoStickWrapObserver<T>(val self:NoStickLiveData<T>,
                                         val observer: Observer<in T>) : Observer<T> {
        private val version: Int = self.mVersion //标记进入的时候的版本

        override fun onChanged(t: T?) {
            if (version < self.mVersion) {
                observer.onChanged(t)
            }
        }
    }

}

//反射的代码 是java版本的
public static Object iteratorGetPrivateFieldValue(Object instance, String fieldName, boolean ignoreSelf) {
        for (Class<?> superClass = ignoreSelf ? instance.getClass().getSuperclass() : instance.getClass();
             superClass != null && superClass != Object.class;
             superClass = superClass.getSuperclass()) {
            try {
                Field field = superClass.getDeclaredField(fieldName);
                field.setAccessible(true);
                return field.get(instance);
            } catch (NoSuchFieldException | IllegalAccessException e) {
            }
        }

        return null;
    }

众所周知,LiveData是粘性的。即,当liveData赋值过(或者初始化默认有值),则当监听observe的瞬间,立刻回调给你的监听函数。

想要破除粘性,我翻阅了一些代码,写的五花八门。我这边也是将我个人的实现方案写在这里。
仔细阅读liveData源码,关键点是mVersion三个变化:

  • 空构造体赋值-1
  • 有参数构造体赋值0
  • 随后setValue每次++

而业务代码注册监听的函数observe(owner, observer) 或者observeForever(observer)
都是经过了包装,
LifecycleBoundObserver(owner, observer)
AlwaysActiveObserver(observer)

都放在了全局变量map,mObservers里面。key就是我们传入的变量observer。

直到removeObserver的时候,通过mObservers.remove(observer)来移除。

因此,类似的,我们只需要继承它,同时也借鉴:

  1. 也在setValue每次把自定义的版本号mVersion++以表征值的更新;
  2. 然后我们把用户代码的observe或者observeForever进行一次NoStickWrapObserver包装。只有当version有变大才通知即可;
  3. 移除的时候,就要考虑了。因为父类中mObservers存储的key,就是我们的NoStickWrapObserver,因此,我们需要将用户的observer,反射拿到父类对象map再找出我们的包装类,再去移除。

本代码的好处,
第一,反射只一次,因为mObservers在LiveData是final的全局变量,不会变化,性能损失可以忽略。
第二,与源代码LiveData的思想高度统一,通过wrap用户的observer存起来的思路。
第三,代码量极少;
第四,最重要的,你如果你想要原来的逻辑的LiveData就按照之前的写法;如果想注册一个后续监听的则调用observeUnStick即可,灵活且方便。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值