В конце концов, я нашел обходной путь для этой проблемы. Мне пришлось отказаться от оперативных данных, которые генерируют одно событие, поскольку они не могли вести себя так, как мне нужно.
Вместо этого я использовал простые изменяемые оперативные данные, которые создают объект события, который оборачивает данные, как в последнем абзаце этого статья Хосе Альсеррека.
Я показываю фрагменты в пейджере, поэтому в данный момент у меня есть только один видимый фрагмент.
Итак, моя модель представления выглядит так:
class ActionViewModel : ViewModel() {
private val onCreateLiveData: MutableLiveData<Event<String>> = MutableLiveData()
fun observeOnCreateEvent(): LiveData<Event<String>> = onCreateLiveData
fun onCreateCollectionClick(message: String) {
this.onCreateLiveData.value = Event(message)
}
}
Реализация класса-обертки событий выглядит так:
/*Used as a wrapper for data that is exposed via a LiveData that represents an
event.*/
open class Event<out T>(private val content: T) {
var hasBeenHandled = false
private set // Allow external read but not write
/**
* Returns the content and prevents its use again.
*/
fun getContentIfNotHandled(): T? {
return if (hasBeenHandled) {
null
} else {
hasBeenHandled = true
content
}
}
/**
* Returns the content, even if it's already been handled.
*/
fun peekContent(): T = content
}
Во фрагментах теперь мы можем наблюдать такие события:
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
actionViewModel = ViewModelProviders.of(requireActivity()).get(ActionViewModel::class.java)
actionViewModel.observeOnCreateEvent()
.observe(this, Observer {
it?.takeIf { userVisibleHint }?.getContentIfNotHandled()?.let {
//DO what ever is needed
}
})
}
Свойство фрагмента userVisibleHint возвращает значение true, если фрагмент в данный момент виден пользователю. Поскольку мы показываем только один фрагмент за раз, это работает для нас. Это означает, что фрагмент будет получать доступ к данным события только в том случае, если он виден.
Кроме того, реализация оболочки Event позволяет только одно чтение значения, так что каждый следующий раз, когда Observer получает это событие, его значение будет нулевым, и мы его проигнорируем.
Вывод. Таким образом, мы имитируем живые данные одного события, которые уведомляют только последнего подписавшегося наблюдателя.
person
TheTechWolf
schedule
09.08.2018
MediatorLifeData
(илиTransformations#switchMap
) - это то, что вы могли бы использовать для такого случая - person pskink   schedule 09.08.2018"last or all subscribed observers"
так последнее или все? - person pskink   schedule 09.08.2018MutableLifeData
было бы лучше с переопределенным методомobserve
, где вы вызываете методremoveObservers
, за которым следуетsuper.observe
- таким образом вы уверены, что активен не более одного наблюдателя - person pskink   schedule 09.08.2018