LiveData 粘性事件解决方案 附:简易LiveDataBus

LiveData 粘性事件解决方案

**LiveData源码分析**
private void considerNotify(LiveData.ObserverWrapper observer) {
        if (!observer.mActive) {
            return;
        }
        // Check latest state b4 dispatch. Maybe it changed state but we didn't get the event yet.
        //
        // we still first check observer.active to keep it as the entrance for events. So even if
        // the observer moved to an active state, if we've not received that event, we better not
        // notify for a more predictable notification order.
        if (!observer.shouldBeActive()) {
            observer.activeStateChanged(false);
            return;
        }

        //上面的判断是生命周期的拦截
        //一般事件流程 :new Observe(mVersion=-1)-> 注册观察者(mLastVersion=-1)-> setValue(mVersion++) 
        //粘性事件的流程 :new Observe(mVersion=-1)-> setValue(mVersion++) ->注册观察者(mLastVersion=-1)
        //此时 mLastVersion=-1 , mVersion=0 ,未触发拦截导致首次注册时会触发接口回调造成粘性事件
        if (observer.mLastVersion >= mVersion) {
            return;
        }
        observer.mLastVersion = mVersion;
        //noinspection unchecked
        observer.mObserver.onChanged((T) mData);
    }

解决方案

package com.zwh.livedatabus

import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.Observer

/**
 *  自定义 MutableLiveData 修改粘性事件
 *  auth 周文豪
 */
class MyMutableLiveData<T> : MutableLiveData<T>(){
    override fun observe(owner: LifecycleOwner, observer: Observer<in T>) {
        super.observe(owner, observer)
        hook(observer)
    }

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

    /**
     * 反射获取 mLastVersion 修改值
     */
    fun hook( observer: Observer<in T>) {
        val liveDataClass = LiveData::class.java
        val mObserversField = liveDataClass.getDeclaredField("mObservers")
        mObserversField.isAccessible = true
        val mObservers = mObserversField.get(this)
        val observerClass = mObservers::class.java

        val get = observerClass.getDeclaredMethod("get",Any::class.java)
        get.isAccessible = true
        val entry = get.invoke(mObservers, observer)
        val observerWrapper = (entry as Map.Entry<Any,Any>).value
        val wrapperClass = observerWrapper.javaClass.superclass

        val mLastVersion = wrapperClass.getDeclaredField("mLastVersion")
        mLastVersion.isAccessible = true
        val mVersion = liveDataClass.getDeclaredField("mVersion")
        mVersion.isAccessible = true
        val mVersionValue = mVersion.get(this)
        mLastVersion.set(observerWrapper,mVersionValue)
    }
}

附:LiveDataBus

/**
 *  简易 LiveDataBus
 *  auth 周文豪
 */
object LiveDataBus {

    private val liveDataMap by lazy {
        hashMapOf<String,MutableLiveData<Any>>()
    }

    fun <T>register(key:String):MyMutableLiveData<T>{
        if (!liveDataMap.containsKey(key)){
            liveDataMap.put(key, MyMutableLiveData())
        }
        return liveDataMap.get(key) as MyMutableLiveData<T>
    }
}

使用

        LiveDataBus.register<String>(TAG).observe(this, Observer {
            Log.e(TAG, "MainActivity:"+it )
        })
        LiveDataBus.register<String>(TAG).value = "尝试发送"

你可能感兴趣的:(android,移动开发)