Jetpack--LiveData粘性数据的去除

 在上一篇LiveData的原理分析(https://blog.csdn.net/xxwbwm/article/details/124395615?spm=1001.2014.3001.5501)中发现Google的源码是默认存在粘性数据的,原因:

private void considerNotify(ObserverWrapper observer) {
        if (!observer.mActive) {
            return;
        }
        if (!observer.shouldBeActive()) {
            observer.activeStateChanged(false);
            return;
        }
        //核心判断
        if (observer.mLastVersion >= mVersion) {
            return;
        }
        //核心判断
        observer.mLastVersion = mVersion;
        //noinspection unchecked
        observer.mObserver.onChanged((T) mData);
    }

当先设置数据时mVersion 会从-1自加到0,而此时mLastVersion 依旧为-1,此时if判断不满足会走下面的onChanged将mData数据分发出去。

去除粘性思路:在设置数据后,通过反射将mLastVersion与mVersion对齐,从而是上面的if判断命中,直接返回即可。

首先封装一个LiveDateBus 单例用于上层操作LiveData。

/**
 * 是否去除粘性数据封装
 */
object LiveDateBus {

    private const val TAG: String = "LiveDateBus-vivid"
    private val bus : MutableMap<String,BusMutableLiveData<Any>> by lazy { HashMap() }

    //对外操作接口
    /**
     * isStick : true 启用粘性数据  false 禁止粘性数据
     */
    fun <T> with(key:String,type:Class<T>,isStick:Boolean = false):BusMutableLiveData<T>{
        if(!bus.containsKey(key)){
            bus[key] = BusMutableLiveData(isStick)
        }

        return bus[key] as BusMutableLiveData<T>
    }


    class BusMutableLiveData<T> private constructor(): MutableLiveData<T>(){
        var isStick :Boolean = false

        constructor(isStick: Boolean) :this() {
            this.isStick = isStick
        }

        override fun observe(owner: LifecycleOwner, observer: Observer<in T>) {
            super.observe(owner, observer)

            if(isStick){
                Log.d(TAG, "observe: 启用粘性数据")
            }else{
                hook(observer = observer)
                Log.d(TAG, "observe: 禁止粘性数据")
            }
        }

        //通过反射修改
        private fun hook(observer: Observer<in T>) {
            val liveDateClass = LiveData::class.java
            val mObserversField:Field  = liveDateClass.getDeclaredField("mObservers")
            mObserversField.isAccessible = true

            val mObserverObject :Any = mObserversField.get(this)
            val mObserversClass:Class<*> = mObserverObject.javaClass

            val get :Method = mObserversClass.getDeclaredMethod("get", Any::class.java)  // Any::class.java == Entry<K, V>
            get.isAccessible = true

            val invokeEntry : Any = get.invoke(mObserverObject, observer)

            var observerWrapper :Any? = null
            if(invokeEntry != null && invokeEntry is Map.Entry<*,*>){
                observerWrapper = invokeEntry.value
            }else{
                throw NullPointerException("get invoke invokeEntry is error!")
            }

            if(observerWrapper == null){
                throw NullPointerException("observerWrapper is Null.")
            }

            val superclass: Class<*> = observerWrapper.javaClass.superclass!!
            val mLastVersion:Field = superclass.getDeclaredField("mLastVersion")
            mLastVersion.isAccessible = true

            val mVersion:Field = liveDateClass.getDeclaredField("mVersion")
            mVersion.isAccessible = true

            val mVersionaValue : Any = mVersion.get(this)
            mLastVersion.set(observerWrapper,mVersionaValue)

        }
    }
}

 其次设置数据:通过点击事件启动监听

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        //禁止粘性数据
        LiveDateBus.with("date", String::class.java,false).value = "测试数据1234567890"
        //启用粘性数据
        //LiveDateBus.with("date", String::class.java,true).value = "测试数据1234567890"

        val button = findViewById<Button>(R.id.btn)
        button.setOnClickListener {
            startActivity(Intent(this,MainActivity2::class.java))
        }

    }
}

最后启动监听: 

class MainActivity2 : AppCompatActivity() {
    private  val TAG: String = "MainActivity2-vivid"
    override fun onCreate(savedInstanceState: Bundle?) {

        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main2)

        LiveDateBus.with("date", String::class.java).observe(this){
            Log.d(TAG, "onCreate: 接受到数据是${it}")
        }
    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值