IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> 面试:LiveData的坑数据丢失问题 -> 正文阅读

[移动开发]面试:LiveData的坑数据丢失问题

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"

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2021-12-16 17:47:32  更:2021-12-16 17:48:08 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 9:06:13-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码