Почему наблюдатель MutableLiveData вызывается только один раз, когда setValue() вызывается более одного раза?

Изменяемые LiveData в ViewModel:

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() напрасно. Как ни странно, такого поведения, которое я описываю, не было до недавнего времени, но неясно, что изменилось, что вызвало эти проблемы.


person Ollie C    schedule 21.02.2019    source источник
comment
Какую версию android.arch.lifecycle вы используете?   -  person RadekJ    schedule 21.02.2019
comment
androidx.lifecycle: жизненный цикл-расширения: 2.0.0   -  person Ollie C    schedule 21.02.2019
comment
ваш наблюдатель находится в активном состоянии, когда устанавливаются новые значения?   -  person RadekJ    schedule 22.02.2019


Ответы (1)


Это была проблема жизненного цикла/времени фрагмента, и в конечном итоге она была вызвана мутациями ViewState, происходящими до того, как фрагмент был в активном состоянии, и поэтому LiveData только что получил одно событие, когда фрагмент достиг активного состояния, представляющего все мутации до этого момента в единое начальное событие.

Для исправления были внесены следующие изменения:

onCreate() — создать ViewModel

onViewCreated() - начать наблюдать за LiveData

onResume() / onStart() - сделать сетевой запрос (который запускает поток измененных состояний просмотра)

При отладке этой проблемы было очень полезно добавить к ней ведение журнала, чтобы увидеть, в каком состоянии находился фрагмент: fragmentManager?.registerFragmentLifecycleCallbacks(...)

person Ollie C    schedule 22.02.2019