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"