【问题标题】:Why is MutableLiveData observer called only once when setValue() is called more than once?为什么当 setValue() 被多次调用时 MutableLiveData 观察者只被调用一次?
【发布时间】:2019-02-21 10:27:34
【问题描述】:

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)
}

Fragment 观察到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() 是徒劳的。奇怪的是,我所描述的这种行为直到最近才出现,但目前尚不清楚是什么变化导致了这些问题。

【问题讨论】:

  • 你使用的是哪个版本的android.arch.lifecycle?
  • androidx.lifecycle:lifecycle-extensions:2.0.0
  • 设置新值时,您的观察者是否处于活动状态?

标签: android android-livedata


【解决方案1】:

这是一个 Fragment 生命周期/计时问题,最终是由在 Fragment 处于活动状态之前发生的 ViewState 突变引起的,因此当 Fragment 到达活动状态时,LiveData 仅收到一个事件,表示所有突变最多单个初始事件中的那个点。

为了修复它,进行了以下更改:

onCreate() - 创建 ViewModel

onViewCreated() - 开始观察 LiveData

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-05-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-05
    相关资源
    最近更新 更多