ViewModel
中的可变 LiveData:
val viewStateLiveData: MutableLiveData<SomeViewState> = MutableLiveData()
当网络调用失败时,这个函数(在 ViewModel
中)从主线程调用来更新 View 状态对象(显示一个 Snackbar,但随后重置状态,所以它不是' t 重新显示):
@UiThread
private fun onFailure() {
viewStateLiveData.value = viewStateLiveData.value?.copy(retrievalSuccess = false, showProgress = false)
viewStateLiveData.value = viewStateLiveData.value?.copy(retrievalSuccess = null)
}
fragment 观察MutableLiveData
:
viewModel.viewStateLiveData.observe(this, Observer { viewState ->
Timber.i("Update ViewState: $viewState")
})
但输出是这个单一的观察者调用(代表第二个突变):
Update ViewState: ViewState(retrievalSuccess=null, showProgress=false)
而不是我所期望的,这将是对观察者的两次调用,反射(reflect)了两个突变:
Update ViewState: ViewState(retrievalSuccess=false, showProgress=false)
Update ViewState: ViewState(retrievalSuccess=null, showProgress=false)
为什么 MutableLiveData.setValue()
在两次突变后都没有触发观察者?文档说“设置值。如果有活跃的观察者,该值将被分配给他们。”但很难不得出结论,这不是调用 setValue() 的情况,而是未触发观察者(处于 Activity 状态)。观察者肯定是在 MutableLiveData
突变之前设置的。
我试验了一系列突变,只看到一次对观察者的调用,它接收一个 View 状态对象,该对象组合了所有先前的突变。因此,对 setValue()
的调用正在改变 View 状态,但只有系列中的最后一个调用才会触发观察者。
我尝试使用 postValue()
但没有成功。奇怪的是,我所描述的这种行为直到最近才出现,但目前尚不清楚是什么改变导致了这些问题。
最佳答案
这是一个 Fragment 生命周期/时间问题,最终是由在 Fragment 处于 Activity 状态之前发生的 ViewState 突变引起的,因此当 Fragment 达到 Active 时,LiveData 只收到一个事件,代表所有突变直到该点在单个初始事件中。
为了修复它,进行了这些更改:
onCreate()
- 创建 ViewModel
onViewCreated()
- 开始观察 LiveData
onResume()
/onStart() - 发起网络请求(启动变异 View 状态流)
在调试这个问题时,添加日志记录非常有用,可以查看 Fragment 处于什么状态:fragmentManager?.registerFragmentLifecycleCallbacks(...)
关于android - 为什么在多次调用 setValue() 时 MutableLiveData 观察器只被调用一次?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54804822/