Решение о представлении навигационного компонента Android

#android #kotlin #android-mvvm

#Android #kotlin #android-mvvm

Вопрос:

Я использую навигационный компонент Android в своем проекте. Что меня не устраивает, так это то, что фрагмент принимает решение о переходе фрагмента к следующему переходу фрагмента, т.е

В моем LoginFragment у меня есть это —

 viewModel.onLoginPressed(email, password)
                    .observe(viewLifecycleOwner, Observer {
                      if (it.userLoggedIn) {
                                activity?.findNavController(R.id.nav_host_fragment)
                                    ?.navigate(R.id.action_loginFragment_to_productsFragment)
                      }
})
  

По моему мнению, представление должно быть фиктивным и не должно принимать никаких подобных решений о том, что делать, например, при loginSuccess. За это должна отвечать ViewModel.

Как мне использовать этот навигационный компонент внутри ViewModel?

Комментарии:

1. Вы смешиваете две рекомендации вместе. Представление должно быть фиктивным, но ваша активность — это делегат вашей политики из фреймворка; решение должно быть принято ViewModel, возможно, но окончательное действие должно выполняться либо делегатом созданного вами навигационного контроллера, либо просто интерфейсом, который может реализовать ваша «активность».

Ответ №1:

ViewModel не обязательно знать о навигации, но он знает о событиях и состоянии.

Коммуникация должна быть больше похожа:

NavHostActivity -> Fragment -> ViewModel

У вашего фрагмента есть представления, прослушиватели кликов и состояние. Пользователь вводит пользователя / пароль и нажимает кнопку. Этот прослушиватель onClick сообщит модель представления -> (псевдокод) onUserPressedTheLoginButtonWith(username, password)

ViewModel, в свою очередь, получит это, сделает то, что ему нужно (например, проверьте, вошли ли вы уже в систему или что-то еще, возможно, окончательное решение — перейти к другому фрагменту).

Что будет делать ViewModel, так это предоставлять LiveData, например

 val navigationEvent = LiveData<...>
  

Таким образом, ViewModel будет navigationEvent.postValue(...)

Fragment Следует соблюдать это viewModel.navigationEvent.observe(...) { }

И ТАМ, во фрагменте, он может либо перемещаться напрямую, либо — если у вас есть интерфейс — использовать его как:

yourNavigator.NavigateTo (…) // либо ваша виртуальная машина знает пункт назначения, либо yourNavitagor у navigateToLogin() нее есть конкретный метод, это все «зависит от того, что вам нравится / предпочитаете / и т. Д.».

Вкратце

  1. Узел активности содержит навигационный код, который не имеет значения.
  2. Фрагменты могут взаимодействовать с созданным вами (и, вероятно, внедренным) разделом навигации, или фрагменты просто знают детали и делают это сами.
  3. Фрагменты наблюдают за состоянием / событием навигации из ViewModel.
  4. Фрагменты отправляют события из пользовательского интерфейса (клики, действия и т. Д.) В эту ViewModel
  5. ViewModel решает, что делать, и обновляет «живые данные» (ы) (может быть несколько типов объектов, которые вы хотите наблюдать, а не только навигация).
  6. Фрагменты реагируют на это наблюдение и действуют соответствующим образом, либо делая это сами, либо делегируя (шаг 2 ^).

Вот как я бы это сделал.