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> by lazy { HashMap() }

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

        return bus[key] as BusMutableLiveData
    }


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

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

        override fun observe(owner: LifecycleOwner, observer: Observer) {
            super.observe(owner, observer)

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

        //通过反射修改
        private fun hook(observer: Observer) {
            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
            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

最后启动监听: 

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}")
        }
    }
}

你可能感兴趣的:(Jetpack,android,kotlin,android,jetpack)