MutableLiveData 中 setValue() 和 postValue() 的区别
Difference of setValue() & postValue() in MutableLiveData
MutableLiveData
有两种改变值的方法。但是 setValue()
和 postValue()
在 MutableLiveData
.
之间有什么区别
我找不到相同的文档。
这里是classMutableLiveData
,共Android。
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);
}
}
基于文档:
Sets the value. If there are active observers, the value will be
dispatched to them. This method must be called from the main thread.
Posts a task to a main thread to set the given value. If you called this method multiple times before a main thread executed a posted task, only the last value would be dispatched.
总而言之,主要区别是:
setValue()
方法必须从主线程调用。但是,如果您需要从后台线程设置一个值,则应使用 postValue()
。
Sets the value. If there are active observers, the value will be dispatched to them.
This method must be called from the main thread.
If you need set a value from a background thread, you can use postValue(Object)
Posts a task to a main thread to set the given value.
If you called this method multiple times before a main thread executed a posted task, only the last value would be dispatched.
setValue()
方法必须从主线程调用。如果需要从后台线程设置值,可以使用 postValue()
.
更多here.
setValue()
直接从调用者线程调用,同步通知观察者并立即更改 LiveData
值。它只能从 MainThread 调用。
postValue()
在内部使用类似 new Handler(Looper.mainLooper()).post(() -> setValue())
的内容,因此它在 MainThread 中通过 Handler
运行 setValue
。它可以从任何线程调用。
以上答案全部正确。但还有一个更重要的区别。如果您调用 postValue()
,然后调用 getValue()
,您 可能不会 收到您在 postValue()
中设置的值。如果主线程已经设置了该值,那么您将获得您发布的值,但如果主线程尚未设置该值,那么您将不会获得您发布的值。因此,如果您在后台线程中工作,请小心。
这不是上述问题的直接答案。 and 的回答很棒。但我在 MutableLiveData 的 ViewModels 中使用的一个简单经验法则是:
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,其中包含 activity/screen 中多个视图的数据。基本上 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 为您处理它的方式也是您所期望的(在视图中为您显示最新数据)。一切都井井有条。
One LD -> one View. PERFECT
One LD -> multiple views THERE MAY BE A WEIRD BEHAVIOR
TL;博士
- 如果您在主线程上工作,那么 setValue 和 postValue 将以相同的方式工作,即它们将更新值并通知观察者。
- 如果在某些后台线程中工作,则不能使用 setValue。你必须在这里与一些观察者一起使用 postValue 。
更多here
如果设置该值需要很长时间(例如,如果您必须从响应速度可能很慢的远程源检索其他数据),请使用 postValue() 这样您就不会锁定主线程。
当保证快速设置值时(通常如此),setValue() 是最简单和最好的。
postValue - 可以在任何地方使用
setValue - 仅来自 main/UI 线程
基本上,postValue 应该只在后台线程中使用,因为它可能比 setValue 慢,后者反应更快。
我写了一个片段来处理这两种情况:
/**
* Live data thread-safe set-value
* Context:
*/
fun <T> MutableLiveData<T>.assignValue(newValue: T){
if(Looper.myLooper() == Looper.getMainLooper()) {
this.value = newValue
}
else {
this.postValue(newValue)
}
}
MutableLiveData
有两种改变值的方法。但是 setValue()
和 postValue()
在 MutableLiveData
.
我找不到相同的文档。
这里是classMutableLiveData
,共Android。
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);
}
}
基于文档:
Sets the value. If there are active observers, the value will be dispatched to them. This method must be called from the main thread.
Posts a task to a main thread to set the given value. If you called this method multiple times before a main thread executed a posted task, only the last value would be dispatched.
总而言之,主要区别是:
setValue()
方法必须从主线程调用。但是,如果您需要从后台线程设置一个值,则应使用 postValue()
。
Sets the value. If there are active observers, the value will be dispatched to them.
This method must be called from the main thread.
If you need set a value from a background thread, you can use
postValue(Object)
Posts a task to a main thread to set the given value.
If you called this method multiple times before a main thread executed a posted task, only the last value would be dispatched.
setValue()
方法必须从主线程调用。如果需要从后台线程设置值,可以使用 postValue()
.
更多here.
setValue()
直接从调用者线程调用,同步通知观察者并立即更改 LiveData
值。它只能从 MainThread 调用。
postValue()
在内部使用类似 new Handler(Looper.mainLooper()).post(() -> setValue())
的内容,因此它在 MainThread 中通过 Handler
运行 setValue
。它可以从任何线程调用。
以上答案全部正确。但还有一个更重要的区别。如果您调用 postValue()
,然后调用 getValue()
,您 可能不会 收到您在 postValue()
中设置的值。如果主线程已经设置了该值,那么您将获得您发布的值,但如果主线程尚未设置该值,那么您将不会获得您发布的值。因此,如果您在后台线程中工作,请小心。
这不是上述问题的直接答案。
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,其中包含 activity/screen 中多个视图的数据。基本上 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 为您处理它的方式也是您所期望的(在视图中为您显示最新数据)。一切都井井有条。
One LD -> one View. PERFECT
One LD -> multiple views THERE MAY BE A WEIRD BEHAVIOR
TL;博士
- 如果您在主线程上工作,那么 setValue 和 postValue 将以相同的方式工作,即它们将更新值并通知观察者。
- 如果在某些后台线程中工作,则不能使用 setValue。你必须在这里与一些观察者一起使用 postValue 。 更多here
如果设置该值需要很长时间(例如,如果您必须从响应速度可能很慢的远程源检索其他数据),请使用 postValue() 这样您就不会锁定主线程。
当保证快速设置值时(通常如此),setValue() 是最简单和最好的。
postValue - 可以在任何地方使用
setValue - 仅来自 main/UI 线程
基本上,postValue 应该只在后台线程中使用,因为它可能比 setValue 慢,后者反应更快。
我写了一个片段来处理这两种情况:
/**
* Live data thread-safe set-value
* Context:
*/
fun <T> MutableLiveData<T>.assignValue(newValue: T){
if(Looper.myLooper() == Looper.getMainLooper()) {
this.value = newValue
}
else {
this.postValue(newValue)
}
}