Я использую навигацию для Android, которая была представлена на Google I / O 2018, и кажется, что я могу использовать ее, привязав к некоторому представлению или используя NavHost, чтобы получить его из фрагмента. Но мне нужно перейти к другому конкретному представлению из ViewModel из моего первого фрагмента в зависимости от нескольких условий. Для ViewModel я расширяю AndroidViewModel, но не понимаю, что делать дальше. Я не могу преобразовать getApplication в Fragment / Activity и не могу использовать NavHostFragment. Также я не могу просто привязать навигацию к onClickListener, потому что startFragment содержит только один ImageView. Как мне перейти с ViewModel?
class CaptionViewModel(app: Application) : AndroidViewModel(app) {
private val dealerProfile = DealerProfile(getApplication())
val TAG = "REGDEB"
fun start(){
if (dealerProfile.getOperatorId().isEmpty()){
if (dealerProfile.isFirstTimeLaunch()){
Log.d(TAG, "First Time Launch")
showTour()
}else{
showCodeFragment()
Log.d(TAG, "Show Code Fragment")
}
}
}
private fun showCodeFragment(){
//??
}
private fun showTour(){
//??
}
}
Мой фрагмент
class CaptionFragment : Fragment() {
private lateinit var viewModel: CaptionViewModel
private val navController by lazy { NavHostFragment.findNavController(this) }
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
viewModel = ViewModelProviders.of(this).get(CaptionViewModel::class.java)
return inflater.inflate(R.layout.fragment_caption, container, false)
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
viewModel.start()
}
}
Хочу сохранить логику навигации в ViewModel
У меня там будет несколько бэкендов, и я буду знать, куда идти. Должен быть способ сделать это
Затем вам нужно распространить эти параметры как состояние на пользовательский интерфейс и принять решение там. ViewModel не должен ничего знать о представлении, поэтому в соответствии с его архитектурой он просто передает данные некоторому представлению, которое будет подпадать под его данные. Возможно, вы ищете архитектуру, в которой ViewModel может активно изменять View. Это будет архитектура MVP, где докладчик может активно изменять представление
Несмотря на то, что я пытался выполнить эту навигацию в классе Fragment, произошла ошибка FragmentManager is already executing transactions
Я согласен со всем, что сказал @LeviAlbuquerque. Не видел вашего кода, но это может быть проблема, который будет исправлен в alpha02
How can I navigate from ViewModel?
Ответ: пожалуйста, не надо. ViewModel предназначен для хранения данных, связанных с пользовательским интерфейсом, и управления ими.
Новый ответ
В своих предыдущих ответах я сказал, что нам не следует переходить из ViewModel, и причина в том, что для навигации ViewModel должен иметь ссылки на Activity / Fragments, которые, как я считаю (возможно, не самые лучшие, но все же я верю в это), никогда не хорошая идея.
Но в рекомендуемой архитектуре приложения от Google упоминается, что мы должен выводить пользовательский интерфейс из модели. И после того, как я подумаю, что они имеют в виду?
Итак, я проверил образец из "android-architecture" и нашел интересный способ, как это сделал Google.
Пожалуйста, проверьте здесь: todo-mvvm-привязка данных
Как оказалось, они действительно вывести пользовательский интерфейс из модели. Но как?
Почему за состояние навигации приложения отвечает View? Представление отвечает за отображение данных, а не за то, чтобы знать, какой экран показывать следующим.
Я не сказал, что это ответственность View. Но ViewModel также не несет ответственности за это. Навигация по ViewModel никогда не бывает хорошей идеей.
Я думаю, вы должны хотя бы объяснить, почему это «никогда не бывает хорошей идеей».
ViewModel - это подходящее место для навигации, просто в Android это становится проблемой, потому что нам нужен доступ к представлению для выполнения этой навигации. Также нет хорошего способа абстрактной навигации. Итак, вообще говоря, навигацию с виртуальной машины на Android не так просто выполнить, но на других платформах это возможно.
Я отредактировал ответы, и, надеюсь, вы понимаете.
Просто ради интереса, мне больше нравится текущий ответ Йози. Мы использовали Cicerone, и у него есть объект Router, который предоставляет доступ для выполнения навигации из ViewModel, и это работает довольно хорошо. Возможно, в какой-то момент мне придется посмотреть, что потребуется для интеграции Цицерона с компонентом навигации.
Я могу ошибаться или опаздывать, но разве эта стратегия не передает ссылку на представление модели представления? что могло привести к утечке памяти
Библиотека навигации - это в первую очередь компонент пользовательского интерфейса, вам необходимо сохранить логику пользовательского интерфейса в пользовательском интерфейсе, поэтому вам необходимо выполнить навигацию во фрагменте / действии.