155

有两种方法可以改变 的值MutableLiveDatasetValue()但是& postValue()in之间有什么区别MutableLiveData

我找不到相同的文档。

这是MutableLiveDataAndroid的类。

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);
    }
}
4

9 回答 9

266

根据文档:

设置值()

设置值。如果有活跃的观察者,值将被分派给他们。必须从主线程调用此方法。

后值()

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

总而言之,主要区别在于:

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

于 2018-07-12T07:28:25.133 回答
148

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

于 2018-09-07T18:06:19.177 回答
27

setValue()直接从调用者线程调用,同步通知观察者并LiveData立即更改值。它只能从 MainThread 调用。
postValue()在类似 this 的内部使用,new Handler(Looper.mainLooper()).post(() -> setValue())因此它在 MainThread 中运行。它可以从任何线程调用。setValueHandler

于 2018-07-12T07:31:25.570 回答
14

setValue()

设置值。如果有活跃的观察者,值将被分派给他们。

必须从主线程调用此方法

postValue

如果您需要从后台线程设置一个值,您可以使用postValue(Object)

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

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

于 2018-07-12T07:28:47.047 回答
11

这不是上述问题的直接答案。Sagarw201的答案很棒。但是我在 ViewModels for MutableLiveData 中使用的一个简单的经验法则是:

private boolean isMainThread() {
    return Looper.myLooper() == Looper.getMainLooper();
}

private MutableLiveData<Boolean> mutVal = new MutableLiveData<>(false);
public LiveData<Boolean> getMutVal() { return this.mutVal;  }
public void setMutVal(boolean val) {
    if (isMainThread()) mutVal.setValue(val);
    else mutVal.postValue(val);
}

替换mutVal为您想要的值。

于 2019-12-16T11:22:00.850 回答
6

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

更多在这里

于 2018-07-12T07:28:48.890 回答
4

TL; 博士

  • 如果您在主线程上工作,那么 setValue 和 postValue 将以相同的方式工作,即它们将更新值并通知观察者。
  • 如果在某个后台线程中工作,则不能使用 setValue。你必须在这里与一些观察者一起使用 postValue 。更多在这里
于 2021-07-31T21:29:20.283 回答
1

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

所以 LD 看起来像这样:

LD {
   state (view_1, view_2, view_3 …),
   model_that_contains_data_of_all_views
}

当一个事件发生时,有几个视图(view_1 和 view_2)必须更新..意味着他们应该在事件发生的同时得到通知。所以,我打电话给:

postData(LD(view_1, data))
postData(LD(view_2, data)

由于我们知道的原因,这行不通。

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

一个 LD -> 一个视图。完美的

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

于 2020-06-22T11:11:11.690 回答
1

如果设置该值需要很长时间(例如,如果您必须从响应缓慢的远程源检索其他数据),请使用 postValue() 这样您就不会锁定主线程。

当设置值保证很快(通常是这样)时, setValue() 是最简单和最好的。

于 2022-01-15T12:15:21.967 回答