Каждый раз, когда вы вызываете .observe()
в LiveData, наблюдатель получает последнее значение этих LiveData.Это может быть полезно в некоторых случаях, но не в моем.
Всякий раз, когда я вызываю .observe()
, я хочу, чтобы наблюдатель получал только будущие изменения LiveData, но не значение, которое он имеет при вызове .observe()
.
У меня может быть несколько наблюдателей для экземпляра LiveData.Я хочу, чтобы все они получали обновления LiveData, когда они происходят.
Я хочу, чтобы каждое обновление LiveData использовалось только один раз каждым наблюдателем. Я думаю, чтопросто перефразирую первое требование, но моя голова уже кружится, и я не уверен в этом.
При поиске этой проблемы я столкнулся с двумя общимиподходы:
Оберните данные в LiveData<SingleEvent<Data>>
и проверьте в этом классе SingleEvent
, если они уже были использованы.
Расширьте MediatorLiveData
и используйте справочную карту, если Наблюдатель уже получил Событие
Примеры этих подходов можно найти здесь: https://gist.github.com/JoseAlcerreca/5b661f1800e1e654f07cc54fe87441af#gistcomment-2783677 https://gist.github.com/hadilq/f095120348a6a14251a02aca329f1845#file-liveevent-kthttps://gist.github.com/JoseAlcerreca/5b661f1800e1e654f07cc54fe87441af#file-event-kt
К сожалению, ни один из этих примеров не отвечает всем моим требованиям.В большинстве случаев проблема заключается в том, что любой новый Observer по-прежнему получает последнее значение LiveData после подписки.Это означает, что Snackbar, который уже был показан, отображается снова и снова, когда пользователь перемещается между экранами.
Чтобы дать вам некоторое представление о том, о чем я говорю / о чем я кодирую:
Я слежу за дизайном LiveData MVVM компонентов архитектуры Android:
- 2 ListFragment показывает список записей.
- Они используют 2 экземпляра одного и того же класса ViewModel для наблюдения связанных с пользовательским интерфейсом LiveData.
- Пользователь может удалить запись в таком ListFragment.Удаление выполняется с помощью ViewModel, вызывая
Repository.delete()
- ViewModel наблюдает за репозиторием для
RepositoryEvents
.
Поэтому, когда удаление выполнено, репозиторий информирует об этом ViewModelи ViewModel информирует об этом ListFragment.
Теперь, когда пользователь переключается на второй ListFragment, происходит следующее:
Вот некоторый упрощенный код:
Фрагмент:
viewModel.dataEvents.observe(viewLifecycleOwner, Observer { showSnackbar() })
viewModel.deleteEntry()
Модель представления:
val dataEvents: LiveData<EntryListEvent> = Transformations.switchMap(repository.events, ::handleRepoEvent)
fun deleteEntry() = repository.deleteEntry()
private fun handleRepoEvent(event: RepositoryEvent): LiveData<EntryListEvent> {
// convert the repository event to an UI event
}
Хранилище:
private val _events = MutableLiveData<RepositoryEvent>()
val events: LiveData<RepositoryEvent>
get() = _events
fun deleteEntry() {
// delete it from database
_events.postValue(RepositoryEvent.OnDeleteSuccess)
}