#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()
нее есть конкретный метод, это все «зависит от того, что вам нравится / предпочитаете / и т. Д.».
Вкратце
- Узел активности содержит навигационный код, который не имеет значения.
- Фрагменты могут взаимодействовать с созданным вами (и, вероятно, внедренным) разделом навигации, или фрагменты просто знают детали и делают это сами.
- Фрагменты наблюдают за состоянием / событием навигации из ViewModel.
- Фрагменты отправляют события из пользовательского интерфейса (клики, действия и т. Д.) В эту ViewModel
- ViewModel решает, что делать, и обновляет «живые данные» (ы) (может быть несколько типов объектов, которые вы хотите наблюдать, а не только навигация).
- Фрагменты реагируют на это наблюдение и действуют соответствующим образом, либо делая это сами, либо делегируя (шаг 2 ^).
Вот как я бы это сделал.