您当前的位置: 首页 >  面试
  • 0浏览

    0关注

    674博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

面试:LiveData的坑数据丢失问题

沙漠一只雕得儿得儿 发布时间:2021-12-15 20:17:09 ,浏览量:0

setValue在主线程中更新数据,postValue在子线程中更新数据调用 

//主线程更新数据调用
sampleLiveData.setValue(data);

//子线程更新数据调用
sampleLiveData.postValue(data);

LiveData会造成数据丢失 

参考:Android开发把 LiveData 用于事件传递那些坑_chuhe1989的博客-CSDN博客_android livedata 混淆

postValue 只是把传进来的数据先存到 mPendingData,然后往主线程抛一个 Runnable,在这个 Runnable 里面再调用 setValue 来把存起来的值真正设置上去,并回调观察者们。而如果在这个 Runnable 执行前多次 postValue,其实只是改变暂存的值 mPendingData,并不会再次抛另一个 Runnable。这就会出现后设置的值把前面的值覆盖掉的问题,会导致事件丢失。  

protected void postValue(T value) {
    boolean postTask;
    synchronized (mDataLock) {
        postTask = mPendingData == NOT_SET;
        // 这里先把数据暂存起来,后来的数据会覆盖前面的
        mPendingData = value;
    }
    // 这里保证只抛一个 mPostValueRunnable,#-.-
    if (!postTask) {
        return;
    }
    ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
}
 

setValue 不回调观察者

LiveData 的生命周期感知能力就体现在这里,它不会回调处于「非激活状态」(即 onStart 之后到 onPause 之前)的观察者,因为这时更新 View 没有意义,而且比较危险,它会等到观察者激活之后再把新的值回调给他。 但是如果我传了多个数据(假设都是用 setValue 保证不会被覆盖),那些处于非激活状态的观察者是毫不知情的,他们在激活的时候只会收到最后一个数据。这对于事件传递来说,就表现为事件丢失,中间传的任何数据都无法收到,那也就失去了事件传递的意义。  

关于更新数据丢失问题

LiveData特性与数据丢失问题或异常问题解析 - 简书

在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"

关注
打赏
1657159701
查看更多评论
立即登录/注册

微信扫码登录

0.0488s