LiveData出现的问题

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)
           }
       }
    
  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值