наблюдатель livedata вызывается каждый раз при возврате к фрагменту

#android #kotlin #android-livedata

#Android #kotlin #android-livedata

Вопрос:

У меня есть fragment1, из которого я перехожу к fragment2. Проблема в том, что я не могу вернуться к fragment1 из fragment2, вот как я обрабатываю нажатие кнопки

 val onClickLiveData = MutableLiveData<OnClick>()

fun onClick() {
    onClickLiveData.value = OnClick.CLICK
}
  

Вот как я обрабатываю переход к fragment2

    private fun subscribeToClickCallbacks() {
    viewModel.onClickLiveData.observe(viewLifecycleOwner, Observer {
            findNavController().navigate(R.id.action_home_fragment_to_repositories_fragment)
    })
}
  

Я обрабатываю переход обратно следующим образом

  navController.popBackStack()
  

С помощью debug я обнаружил, что при каждом переходе к fragment1 вызывается livedata и мгновенно открывает fragment2.

Как можно решить проблему? Я был бы благодарен за каждый ответ.

Ответ №1:

Если текущие данные являются наблюдателем несколько раз, используйте SingleEvent для обработки этого случая. Создайте один глобальный класс для SingleLiveData следующим образом.

 class SingleLiveEvent<T> : MutableLiveData<T>() {

    private val mPending = AtomicBoolean(false)

    @MainThread
    override fun observe(owner: LifecycleOwner, observer: Observer<T>) {

        if (hasActiveObservers()) {
            Log.w(TAG, "Multiple observers registered but only one will be notified of changes.")
        }

        // Observe the internal MutableLiveData
        super.observe(owner, object : Observer<T> {
            override fun onChanged(t: T?) {
                if (mPending.compareAndSet(true, false)) {
                    observer.onChanged(t)
                }
            }
        })
    }

    @MainThread
    override fun setValue(t: T?) {
        mPending.set(true)
        super.setValue(t)
    }

    /**
     * Used for cases where T is Void, to make calls cleaner.
     */
    @MainThread
    fun call() {
        setValue(null)
    }

    companion object {

        private val TAG = "SingleLiveEvent"
    }
}
  

Теперь используйте этот класс следующим образом,

 val onClickLiveData = SingleLiveEvent<OnClick>()