Как остановить событие 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 Надеюсь, это поможет, наслаждайтесь!

Другие вопросы по тегам