android - 为什么在多次调用 setValue() 时 MutableLiveData 观察器只被调用一次?

标签 android android-livedata

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/

相关文章:

android - 在特定时间触发函数(代码)

android - 在框架布局上设置动态创建的 TextView

java - 将模块从应用程序转换为功能后到处都是 "Cannot resolve R"

2.6.0 版本后找不到 androidx.lifecycle.LiveDataReactiveStreams 类

android - 将MutableLiveData传递给其他ViewModel是否有效?

android - Kotlin Android : Property delegate must have a 'getValue(DashViewModel, KProperty*>)' method

android - 如何计算设备最近在 Android 中解锁的时间?

Android 如何让 scrollView 在点击 editText 时自动滚动到底部?

android - 如何从 Android LiveData<List<T>> 获取简单的 List<T>?

android - 类型不匹配。必需:观察员<in int!>找到:?