MutableLiveData 中 setValue ()和 postValue ()的差异

MutableLiveData的变化有两种方式,但 MutableLiveDatasetValue()postValue()的变化有什么不同。

我找不到相同的文档。

这是 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);
}
}
102905 次浏览

根据文件:

SetValue () :

设置值。如果有活动的观察者,值将为 这个方法必须从主线程调用。

PostValue () :

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

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

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

setValue()

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

必须从主线程 调用此方法。

postValue

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

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

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

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

更多 给你

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

以上所有答案都是正确的。但还有一个重要的区别。如果调用 postValue()并在此之后调用 getValue(),则 也许不会将收到在 postValue()中设置的值。如果主线程已经设置了该值,那么您将获得您发布的值,但是如果主线程尚未设置该值,那么您将无法获得您发布的值。因此,如果使用后台线程,请小心。

这不是上述问题的直接答案。来自 SagarW201的答案是令人敬畏的。但是我在 ViewModelforMutableLiveData 中使用的一个简单的经验法则是:

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

在我们的应用程序中,我们使用了单个 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,postData 处理它的方式也是您所期望的(在视图中为您显示最新数据)。一切都井井有条。

一个 LD-> 一个查看

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

DR

  • 如果您正在处理主线程,那么 setValue 和 postValue 将以相同的方式工作,即它们将更新值并通知观察者。
  • 如果在某个后台线程中工作,那么就不能使用 setValue。 More < a href = “ https://blog.mindorks.com/livedata-setvalue-vs-postvalue-in-android”rel = “ noReferrer”> here

如果设置值需要很长时间(例如,如果必须从远程源检索额外的数据,而这些数据的响应速度可能很慢) ,那么使用 postValue () ,这样就不会锁定主线程。

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

PostValue-可以从任何地方使用

来自主线程/UI 线程的 setValue-only

基本上,postValue 应该只从后台线程使用,因为它可能比 setValue 反应更快,所以速度更慢。

我已经写了一段代码来处理这两种情况:

/**
* Live data thread-safe set-value
* Context: https://stackoverflow.com/a/52227632/6688493
*/
fun <T> MutableLiveData<T>.assignValue(newValue: T){


if(Looper.myLooper() == Looper.getMainLooper()) {
this.value = newValue
}
else {
this.postValue(newValue)
}
}