Я слежу за архитектурой MMVM в приложении. Все работало нормально, пока я не получил сбой, используя следующий код для запуска активности из ViewModel. Метод вызывается из XML с использованием привязок данных и передачей view в качестве параметра, а getApplication() - это метод из класса AndroidViewModel.
getApplication().startActivity(new Intent(view.getContext(), MyActivity.class));
Я считаю, что это произошло из-за того, что я не использую флаг NEW_TASK, так как начинаю деятельность вне класса Activity.
Теперь есть следующие решения, о которых я мог подумать, но не уверен, какое из них лучше всего с архитектурной точки зрения.
1. ViewModel с методом, который принимает Activity в качестве параметра и вызывает этот метод из фрагмента.
public startMyActivity(Activity activity){
activity.startActivity(new Intent(activity, MyActivity.class));
}
Теперь добавьте листнер примерно так во фрагменте
mBinding.myButton.setOnClickListener(){
viewModel.startMyActivity(getActivity());
}
2. Добавление флага «Новая задача» в намерение и сохранение его в самой ViewModel.
Intent myIntent = new Intent(view.getContext(), MyActivity.class);
myIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
getApplication().startActivity(myIntent);
3. Запустите Activity из самого фрагмента.
mBinding.myButton.setOnClickListener(){
activity.startActivity(new Intent(activity, MyActivity.class));
}
Я считаю, что все эти подходы работают нормально, но есть вопрос
Можно ли иметь слушателей отдельно во фрагменте с использованием привязанных ViewModels для вызова метода из представления xml?
Я не уверен насчет второго подхода, если это все равно приведет к сбою приложения в какой-либо ОС.
Какой из них является лучшим с точки зрения архитектуры и перспективы модульного тестирования?
@ChintanSoni Я согласен, это не ссылка, которую он передает из привязки данных к методу прослушивателей кликов, я считаю, что это должно быть хорошо.
@MuhammadBabar, кто должен начинать действие тогда и как, потому что в идеале все взаимодействия с представлениями должны обрабатываться в моделях представлений.
Да, вы правы, это зависит от обстоятельств, если у вас есть доступный контекст активности, то лучше всего использовать NEW_TASK, контекст активности недоступен, например, в широковещательном приемнике или службе и т. д.
Я бы пошел для навигации внутри действий / фрагментов, но, конечно, в большинстве случаев вы хотите запускать навигацию из модели представления. Таким образом, вам нужно использовать команду из вашей модели просмотра, чтобы уведомить ваше представление (активность / фрагмент) для навигации в другом месте. Вы можете выполнить такую «команду», используя LiveData, а точнее SingleLiveEvent.
SingleLiveEvent похож на любые LiveData, но запускает событие только тогда, когда вы явно устанавливаете для него значение, например, вы не получите его значение, когда начнете наблюдать за ним из вашего представления (активность / фрагмент)
Спасибо, я попробую и посмотрю, сработает ли это для меня.
Если у меня есть много возможных пунктов назначения с текущего экрана. Должен ли я иметь 1 SingleLiveEvent для каждого возможного пункта назначения? Что для этого лучше всего?
Я выберу одно событие и пункт назначения в качестве аргумента
Следует избегать использования любых представлений Android в ViewModel или AndroidViewModel.