Как остановить событие LiveData, запускаемое более одного раза
Я использую MutableLiveData в моем приложении для связи на основе событий. У меня есть одно занятие с двумя фрагментами архитектуры.
С помощью ViewModel я использую события LiveData в Fragment-1. Но когда я заменяю этот Фрагмент-1 на Фрагмент-2 с помощью строки меню и, наконец, возвращаюсь к Фрагменту-1, старые значения LiveData снова фиксируются.
Как избежать этой проблемы? Любая помощь / предложения высоко ценятся! Спасибо.
5 ответов
Ты можешь использовать Event
обернуть LiveData
значения для обработки потребления его значения, как в следующей статье: https://medium.com/androiddevelopers/livedata-with-snackbar-navigation-and-other-events-the-singleliveevent-case-ac2622673150
Класс события будет выглядеть так:
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
}
Допустим, что вашим значением LiveData является строка, тогда LiveData отдельного события будет выглядеть так:
val navigateToDetails = MutableLiveData<Event<String>>()
Проблема с принятым ответом в том, что у вас может быть только один наблюдатель. В этой статье описывается решение с несколькими наблюдателями.
Где бы вы ни смотрели liveData, в onChanged
метод удалить наблюдателей, вызвав myLiveDataObject.removeObservers(this);
Это удалит наблюдателя после первого наблюдения данных.
Простой, чистый, многоразовый:
class Event<T>(val payload: T, var broadcasted: Boolean = false)
class MutableEventLiveData<T>: MutableLiveData<Event<T>>() {
fun postEvent(value: T) {
super.postValue(Event(value))
}
}
typealias EventLiveData<T> = LiveData<Event<T>>
class EventObserver<T>(private val broadcastCallback: (t: T)->Unit): Observer<Event<T>> {
override fun onChanged(e: Event<T>) {
if (!e.broadcasted) {
broadcastCallback(e.payload)
e.broadcasted = true
}
}
}
Пример использования:
class YourViewModel : ViewModel() {
private val _errorEvent = MutableEventLiveData<String>()
val errorEvent: EventLiveData<String>
get() = _errorEvent
fun fireErrorEvent(errorMessage: String) {
_errorEvent.postEvent(errorMessage)
}
...
}
class YourActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
...
//Note!!! EventObserver handles events not Observer
viewModel.errorEvent.observe(this, EventObserver {
errorMessage -> showErrorMessage(errorMessage)
})
}
...
}
Я столкнулся с той же проблемой и придумал эту библиотеку для ее решения https://github.com/ueen/LiveEvent Надеюсь, это поможет, наслаждайтесь!