Потребитель LiveData в BaseFragment не получает обновления от BaseViewModel

У меня есть BaseFragment.kt, который выглядит так

open class BaseFragment: Fragment() {

private lateinit var viewModel: BaseViewModel

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)
    viewModel = ViewModelProvider(this).get(BaseViewModel::class.java)
    observeNavigationCommands()
}

/**
 * Method that observes Navigation commands triggered by BaseViewHolder
 * This allows us to navigate from a viewHolder using the MVVM pattern
 */
private fun observeNavigationCommands() {
    viewModel.navigationCommands.observe(viewLifecycleOwner, EventObserver {
        Timber.e("received nav command $it")
        when(it) {
            is NavigationCommand.To -> findNavController().navigate(it.destinationId)
            is NavigationCommand.Back -> findNavController().popBackStack()
            is NavigationCommand.BackTo -> TODO()
            NavigationCommand.ToRoot -> TODO()
        }
    })
}

}

... и BaseViewModel.kt, который выглядит так

open class BaseViewModel: ViewModel() {

val navigationCommands = MutableLiveData<Event<NavigationCommand>>()

/**
 * Navigate to a specific fragment using Id
 */
fun navigate(id: Int) {
    Timber.e("trigger navigation event $id")
    // navigationCommands.postValue(NavigationCommand.To(id))
    navigationCommands.value = Event(NavigationCommand.To(id))
}

/**
 * Pop backStack
 */
fun goBack() {
    navigationCommands.value = Event(NavigationCommand.Back)
}

}

класс NavigationCommand выглядит так

sealed class NavigationCommand {

data class To(val destinationId: Int) : NavigationCommand()
data class BackTo(val destinationId: Int): NavigationCommand()

object Back: NavigationCommand()
object ToRoot: NavigationCommand()

}

Теперь в моих других моделях просмотра, которые расширяются BaseViewModel, я хочу иметь возможность звонить navigate(R.id.action_fragmentA_to_fragmentB) но проблема в том, что потребитель в observeNavigationCommands() никогда не получает NavigationCommands

.....

Но если я скопирую содержимое observeNavigationCommands() и помещу его в свой текущий фрагмент (тот, который расширяет BaseFragment), потребитель получит обновления.

что мне не хватает? Пожалуйста помоги

1
0
364
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Правильно ли я понимаю, что для вашего фрагмента, который расширяет BaseFragment, вы хотите прикрепить viewModel, который расширяет BaseViewModel, но это не работает для вас с liveData?

Если это так, ознакомьтесь с этим простым рабочим проектом, который я создал, чтобы отразить ваш случай:

https://github.com/phamtdat/OpenViewModelDemo

Смысл в том, чтобы сделать viewModel переопределяемым и переопределить его в вашем фрагменте, который расширяет BaseFragment.

спасибо за ваше решение, но я хочу иметь возможность вызывать методы навигации из ViewModel, а не из фрагмента... Я изменил ваш код для этого и столкнулся с той же проблемой, что и сейчас. Пожалуйста, измените пустой класс MyViewModel чтобы иметь метод-оболочку, например: fun mNav() { naviagte(123456) } и протестировать, вызвав mNav() вместо navigate(123456) из вашего фрагмента, я уверен, что вы увидите, о чем я говорю

Samuel Agbesinyale 12.12.2020 02:33

Хм, не могу воспроизвести то, что вы описываете. Я вижу журналы, что события были вызваны. Может быть, есть проблема с классом Event, который я не использую, какова для него зависимость build.gradle? Я не использовал его, так как не знал зависимости. Если у вас есть модифицированный код, который воспроизводит проблему, отправьте запрос на включение в репозиторий, и я посмотрю. В любом случае проверьте это, поскольку я сделал обновление с завернутыми функциями.

Dat Pham Tat 12.12.2020 03:54

Кстати, зачем использовать функцию-обертку, а не сделать navigate open fun и переопределить ее в MyViewModel? там вы делаете свою логику и потом вызываете super.navigate(...), и тогда во фрагменте вам не нужно будет делать никакого приведения классов

Dat Pham Tat 12.12.2020 04:04

Спасибо... ваше решение работает, но я создал запрос на включение в репозиторий с некоторыми изменениями, которые пытаются описать мой сценарий... пожалуйста, взгляните...

Samuel Agbesinyale 12.12.2020 21:08

Хорошо, я наконец понял вашу проблему. Проверьте новое обновление репозитория, чтобы узнать, отвечает ли оно на ваш вопрос. Начните с MySampleFragment

Dat Pham Tat 12.12.2020 22:48

Я пытался проголосовать, но моя репутация низкая, ниже 15 :( К сожалению. Судя по всему, это записывается, но не меняет общедоступную оценку публикации.

Samuel Agbesinyale 14.12.2020 20:29

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