MutableLiveData中的setValue()和postValue()的区别

时间:2018-07-12 07:27:06

标签: android android-livedata mutablelivedata

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

我找不到相同的文档。

这是Android的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);
    }
}

8 个答案:

答案 0 :(得分:51)

基于文档:

setValue()

  

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

postValue()

  

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

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

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

答案 1 :(得分:28)

以上所有答案均正确。但是还有一个重要的区别。如果您在没有观察者的字段上调用postValue(),然后再调用getValue(),则不会收到在postValue()中设置的值。因此,如果您在没有观察员的情况下使用后台线程,请当心。

答案 2 :(得分:6)

setValue()

  

设置值。如果有活动的观察者,那么值将分派给他们。

     

必须从主线程调用此方法

postValue

  

如果您需要通过后台线程设置值,则可以使用postValue(Object)

     

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

     

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

答案 3 :(得分:6)

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

答案 4 :(得分:3)

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

更多here

答案 5 :(得分:1)

这不是上述问题的直接答案。来自Sagarw201的答案很棒。但是我在ViewModels中使用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替换为所需的值。

答案 6 :(得分:1)

TL;博士

  • 如果您在主线程上工作,则 setValue 和 postValue 将以相同的方式工作,即它们将更新值并通知观察者。
  • 如果在某个后台线程中工作,则不能使用 setValue。你必须在这里使用 postValue 和一些观察者。 更多here

答案 7 :(得分:0)

在我们的应用中,我们使用了单个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->多个视图可能会有奇怪的行为