1.LiveData的postvalue()存在数据丢失问题
-
从源码中我们发现,当我们调用postValue()时,内部首先将value值存到mPendingData中,然后向主线程调用一个runnable,在runnable中调用setValue将值设置上去,并通过所有的观察者,那么若是在runnable执行之前多次调用postValue(),也只是将之前的值给覆盖了,并不会多次触发runnable,最总runable会被执行一次,设置最后的那个值,从而导致事件丢失
protected void postValue(T value) { boolean postTask; synchronized (mDataLock) { postTask = mPendingData == NOT_SET; // 这里先把数据暂存起来,后来的数据会覆盖前面的 mPendingData = value; } // 这里保证只抛一个 mPostValueRunnable,#-.- if (!postTask) { return; } ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable); }
2.setValue不回调观察者
-
LiveData不会回调处于非激活状态的(onStart之前 onPause之后的)观察者,因为在这个时候更新View是没有什么意义的,它会等到观察者处于激活者状态时再会把状态回传给它,那么这样就会导致在非激活状态下,观察者是会丢失事件
// LiveData 通知观察者时调的函数 private void considerNotify(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; } // 每次更新数据都会版本加一,这里保证不会回调之前发送过的数据 if (observer.mLastVersion >= mVersion) { return; } observer.mLastVersion = mVersion; //noinspection unchecked observer.mObserver.onChanged((T) mData); }
3.数据设置举例
在UI可见时,调用
liveData.postValue("a");
liveData.setValue("b");
会先收到"b",后收到"a"
在UI不可见时,调用
liveData.postValue("a");
liveData.setValue("b");
当UI可见,只会收到"a",因为setValue先执行,之后被postValue更新掉
在UI可见时,调用
liveData.setValue("a");
liveData.setValue("b");
liveData.setValue("c");
liveData.setValue("d");
liveData.setValue("e");
会按顺序收到"a","b","c","d","e"
在UI可见时,调用
liveData.postValue("a");
liveData.postValue("b");
liveData.postValue("c");
liveData.postValue("d");
liveData.postValue("e");
只会收到"e"
在UI可见时,调用
liveData.postValue("a");
liveData.postValue("b");
liveData.postValue("c");
liveData.postValue("d");
liveData.setValue("e");
会先收到"e",后收到"d"
在UI不可见时,调用
liveData.setValue("a");
liveData.setValue("b");
liveData.setValue("c");
liveData.setValue("d");
liveData.setValue("e");
当UI可见之后,只会收到"e"
在UI不可见时,调用
liveData.postValue("a");
liveData.postValue("b");
liveData.postValue("c");
liveData.postValue("d");
liveData.postValue("e");
当UI可见之后,只会收到"e"
在UI不可见时,调用
liveData.setValue("a");
liveData.setValue("b");
liveData.setValue("c");
liveData.setValue("d");
liveData.postValue("e");
当UI可见之后,只会收到"e"
在UI不可见时,调用
liveData.postValue("a");
liveData.postValue("b");
liveData.postValue("c");
liveData.postValue("d");
liveData.setValue("e");
当UI可见之后,只会收到"d"
4.LiveData只会通知处于激活状态下的观察者,对于非激活状态的观察者无论数据发生了多少次变化,都对它无关。只有等到它处于激活状态下,才会将最新值传递给它。因此LiveData并不是为了传递事件的,它是为了反应当前View的状态的
5.如何解决livedata数据丢失问题以及生命周期管理?
-
针对数据丢失的问题,我们发现是因为在postvalue中只抛了一个runnable,那我们只需要每次都抛一个runnable来解决这个问题
import android.os.Handler import android.os.Looper import androidx.lifecycle.MutableLiveData object LiveDataUtils { private var sMainHandler: Handler? = null /** *用于主线程设置value */ fun <T> setValue(data: MutableLiveData<T>, d: T) { if (null == data) { return } //位于主线程 if (Thread.currentThread() == Looper.getMainLooper().thread) { data.value=d //位于工作线程 } else { postValue(data,d) } } /** * 用于子线程设置value */ fun <T> postValue(data: MutableLiveData<T>, d: T) { if(null== sMainHandler){ sMainHandler=Handler(Looper.getMainLooper()) } sMainHandler?.post(SetValueRunnable.createRunnable(data,d)) } private class SetValueRunnable<T>(var liveData: MutableLiveData<T>?,var data:T?):Runnable{ //LiveData private var mLiveData: MutableLiveData<T>?=null //要设置的数据 private var mData:T?=null init { this.mLiveData=liveData this.mData=data } override fun run() { this.mLiveData?.value=this.mData } companion object{ fun <T> createRunnable(liveData: MutableLiveData<T>?,data:T?):SetValueRunnable<T>{ return SetValueRunnable(liveData,data) } } } }
-
针对生命周期管理的问题,我们使用LifecycleOwner、Lifecycle,然后自己观察 LifecycleOwner 的 Lifecycle。当组件的生命周期发生变化的时候我们可以判断是否处于激活状态,若处于非激活状态先将数据存储起来,当生命周期处于激活状态时再将存储起来的数据逐个发送给观察者
import androidx.lifecycle.* import androidx.lifecycle.Observer import java.util.* /** * LiveData用作事件传递的观察者 * 保证事件不会丢失,保存非激活状态事件,并能够在激活状态下回调,且没有内存泄漏 */ class LiveEventObserver<T>(liveData:LiveData<T>?, owner:LifecycleOwner?, observer: Observer<in T>?) : LifecycleObserver,Observer<T>{ //LiveData对象 设置数据 private var mLiveData:LiveData<T>?=null //获取当前生命周期状态 private var mOwner:LifecycleOwner?=null //观察者 private var mObserver: Observer<in T>? = null //存储在非激活状态下传递过来的数据 private var mPendingData:Vector<T> = Vector() init { this.mLiveData=liveData this.mOwner=owner this.mObserver=observer this.mOwner?.let { it.lifecycle?.addObserver(this) } this.mLiveData?.let { it.observeForever(this) } } override fun onChanged(t: T) { if(isActive()){//若处于激活状态 直接更新 mObserver?.onChanged(t) }else{//若处于非激活状态 先把数据存储起来 mPendingData?.addElement(t) } } /** * 是否处于激活状态 */ private fun isActive(): Boolean { return if(null==this.mOwner) false else this.mOwner!!.lifecycle?.currentState?.isAtLeast(Lifecycle.State.STARTED) } /** * onStart 之后就是激活状态了,如果之前存的有数据,就发送出去 */ @OnLifecycleEvent(Lifecycle.Event.ON_ANY) fun onEvent(owner:LifecycleOwner,event: Lifecycle.Event){ if(this.mOwner!=owner){ return } if(Lifecycle.Event.ON_START==event||Lifecycle.Event.ON_RESUME==event){ mPendingData?.forEach { this.mObserver?.onChanged(it) } mPendingData?.clear() } } /** * 解除各种观察者绑定并清空数据 */ @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY) fun onDestroy(){ this.mLiveData?.removeObserver(this) this.mLiveData=null this.mOwner?.lifecycle?.removeObserver(this) this.mOwner=null mPendingData?.clear() } companion object{ /** * 绑定 */ fun <T> bind(liveData:LiveData<T>?, owner:LifecycleOwner?, observer: Observer<in T>?){ if (null==owner||owner.getLifecycle().getCurrentState() == Lifecycle.State.DESTROYED) { return } LiveEventObserver(liveData, owner, observer); } } } import androidx.lifecycle.LifecycleOwner import androidx.lifecycle.MediatorLiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.Observer /** * 事件总线 */ class EventMutableLiveData<T> : MutableLiveData<T>() { override fun observe(owner: LifecycleOwner, observer: Observer<in T>) { LiveEventObserver.bind(this,owner, observer) } override fun postValue(value: T) { LiveDataUtils.setValue(this,value) } } /** * 事件总线 */ class EventMediatorLiveData<T> : MediatorLiveData<T>(){ override fun observe(owner: LifecycleOwner, observer: Observer<in T>) { LiveEventObserver.bind(this,owner, observer) } override fun postValue(value: T) { LiveDataUtils.setValue(this,value) } }