Android 设置值()的差异(&;MutableLiveData中的postValue()

Android 设置值()的差异(&;MutableLiveData中的postValue(),android,android-livedata,mutablelivedata,Android,Android Livedata,Mutablelivedata,有两种方法可以更改MutableLiveData的值。但是MutableLiveData中的setValue()和postValue()之间有什么区别呢 我找不到同样的文档 这是Android的classMutableLiveData package android.arch.lifecycle; /** * {@link LiveData} which publicly exposes {@link #setValue(T)} and {@link #postValue(T)} metho

有两种方法可以更改
MutableLiveData
的值。但是
MutableLiveData
中的
setValue()
postValue()
之间有什么区别呢

我找不到同样的文档

这是Android的class
MutableLiveData

package android.arch.lifecycle;

/**
 * {@link LiveData} which publicly exposes {@link #setValue(T)} and {@link #postValue(T)} method.
 *
 * @param <T> The type of data hold by this instance
 */
@SuppressWarnings("WeakerAccess")
public class MutableLiveData<T> extends LiveData<T> {
    @Override
    public void postValue(T value) {
        super.postValue(value);
    }

    @Override
    public void setValue(T value) {
        super.setValue(value);
    }
}
包android.arch.lifecycle;
/**
*{@link LiveData}公开{@link#setValue(T)}和{@link#postValue(T)}方法。
*
*@param此实例持有的数据类型
*/
@抑制警告(“弱化访问”)
公共类MutableLiveData扩展了LiveData{
@凌驾
公共无效后置值(T值){
super.postValue(value);
}
@凌驾
公共无效设置值(T值){
super.setValue(值);
}
}

基于文档:

:

设置值。如果存在活动的观察者,则该值将为 派去给他们。必须从主线程调用此方法

:


将任务发布到主线程以设置给定值。如果在主线程执行已发布任务之前多次调用此方法,则只会调度最后一个值

总而言之,关键区别在于:

必须从主线程调用
setValue()
方法。但如果需要从后台线程设置值,则应使用
postValue()

设置值。如果存在活动的观察者,则会将值分派给他们

必须从主线程调用此方法

如果需要从后台线程设置值,可以使用
postValue(对象)

将任务发布到主线程以设置给定值


如果在主线程执行已发布任务之前多次调用此方法,则只会调度最后一个值

必须从主线程调用
setValue()
方法。如果需要从后台线程设置值,可以使用
postValue()

更多。

setValue()
直接从调用者线程调用,同步通知观察者并立即更改
LiveData
值。只能从主线程调用它。

postValue()
在类似以下内容的内部使用
新处理程序(Looper.mainLooper()).post(()->setValue())
,因此它通过主线程中的
处理程序运行
setValue
。它可以从任何线程调用。

以上所有答案都是正确的。但还有一个更重要的区别。如果调用
postValue()
,然后调用
getValue()
,则可能不会收到在
postValue()
中设置的值。如果主线程已经设置了值,那么您将获得发布的值,但是如果主线程还没有设置值,那么您将不会获得发布的值。因此,如果在后台线程中工作,请小心。

这不是上述问题的直接答案。来自和的答案非常棒。但我在可变LiveData的ViewModels中使用的一个简单经验法则是:

private boolean isMainThread(){
返回Looper.myLooper()==Looper.getMainLooper();
}
私有MutableLiveData mutVal=新的MutableLiveData(false);
public LiveData getMutVal(){返回this.mutVal;}
公共void setMutVal(布尔值){
if(isMainThread())mutVal.setValue(val);
else mutVal.postValue(val);
}

mutVal
替换为您所需的值。

在我们的应用程序中,我们使用了单个LiveData,其中包含活动/屏幕中多个视图的数据。基本上,N个视图对应N个数据集。这让我们有点困扰,因为postData的设计方式。我们在LD中有state对象,它向视图传递需要更新的视图

所以LD看起来像这样:

LD {
   state (view_1, view_2, view_3 …),
   model_that_contains_data_of_all_views
}
当一个事件发生时,有两个视图(视图1和视图2)必须更新。这意味着它们应该在事件发生的同时得到通知。因此,我打电话:

postData(LD(view_1, data))
postData(LD(view_2, data)
由于我们知道的原因,这是行不通的

我的理解是,基本上一个LD应该只代表一个视图。这样就不可能连续调用postData()两次。即使您调用,postData为您处理它的方式也是您所期望的(在视图中为您显示最新数据)。一切都井然有序

一个LD->一个视图完美

一个LD->多个视图可能有奇怪的行为


但愿我能投票!基于此,如果可能,最好使用
setValue()
,只有在必要时才谨慎使用“postValue()”。谢谢,这里没有“最好”的方法。如果您使用后台线程中的LiveData,则应该使用postValue。在最新版本的生命周期组件中,它修复了。。。很可能。“在最新版本的生命周期组件中,它也修复了……很可能。”您有关于这方面的更多信息吗?ThanksI做了一些测试,似乎在最后一个版本的lib中,一切都正常工作。你能给我看一下上面的具体代码吗?如果在ViewModel中,我像
noobservevidata.postValue(“示例”)
一样实现,在Activity中,当我像
ViewModel.noobservevidata.getValue那样使用getValue时,你的意思是不是不是不是我在postValue()中设置的值(“示例”)?“只会调度最后一个值”。我无法通过阅读代码来确定这一点。因此,似乎一旦第一个线程即将命中postValue()内的内部同步块,下一个CPU窗口就有可能被赋予正在发布另一个值的线程2。然后,线程2可以完成同步块,调度程序为第一个线程提供一个自行运行的窗口。现在,它高估了线程2已经编写的内容。这有可能吗?重要提示:I ju