为什么当setValue()被多次调用时,MutableLiveData观察器仅被调用一次?

时间:2019-02-21 10:27:35

标签: android android-livedata

ViewModel中的可变LiveData:

val viewStateLiveData: MutableLiveData<SomeViewState> = MutableLiveData()

当网络调用失败时,将从主线程中调用此函数(在ViewModel中)以更新视图状态对象(以显示Snackbar,然后重置状态,这样就不会重新显示):

@UiThread
private fun onFailure() {
    viewStateLiveData.value = viewStateLiveData.value?.copy(retrievalSuccess = false, showProgress = false)
    viewStateLiveData.value = viewStateLiveData.value?.copy(retrievalSuccess = null)
}

该片段观察到MutableLiveData

    viewModel.viewStateLiveData.observe(this,  Observer { viewState ->
        Timber.i("Update ViewState: $viewState")
    })

但是输出是单个观察者调用(代表第二个突变):

Update ViewState: ViewState(retrievalSuccess=null, showProgress=false)

而不是我所期望的,这是对观察者的两次调用,反映了两种变异:

Update ViewState: ViewState(retrievalSuccess=false, showProgress=false)
Update ViewState: ViewState(retrievalSuccess=null, showProgress=false)

为什么MutableLiveData.setValue()在两个突变之后都没有触发观察者?文档说:“设置值。如果有活动的观察者,该值将分派给他们。”但是很难断定并非如此,因为正在调用setValue(),但是没有触发观察器(处于活动状态)。观察者肯定是在MutableLiveData突变之前建立的。

我尝试了一系列突变,但只看到一个观察者调用,该观察者接收到一个结合了所有先前突变的视图状态对象。因此,对setValue()的调用改变了视图状态,但是只有系列中的最后一个调用才触发观察者。

我尝试徒然使用postValue()。奇怪的是,我要描述的这种行为直到最近才出现,但尚不清楚是什么引起了这些问题。

1 个答案:

答案 0 :(得分:0)

这是一个Fragment生命周期/定时问题,最终是由Fragment处于活动状态之前发生的ViewState突变引起的,因此,当Fragment到达Active时,LiveData只是收到一个事件,代表了直至在单个初始事件中就是这一点。

要解决此问题,请进行以下更改:

onCreate()-创建ViewModel

onViewCreated()-开始观察LiveData

onResume() / onStart()-发出网络请求(启动已突变视图状态流)

在调试此问题时,向其中添加日志记录以查看Fragment处于什么状态确实很有帮助:fragmentManager?.registerFragmentLifecycleCallbacks(...)