#android #kotlin #android-jetpack-compose #android-architecture-navigation
#Android #котлин #android-jetpack-сочинять #android-архитектура-навигация
Вопрос:
У меня есть такая структура:
val navController = rememberNavController() NavHost( navController = navController, startDestination = "auth" ) { composable( route = "auth" ) { AuthScreen( navController = navController ) } composable( route = "profile" ) { ProfileScreen( navController = navController ) } }
Когда я впервые открываю приложение, я отображаю экран в соответствии с состоянием аутентификации:
if (!viewModel.isUserAuthenticated) { AuthScreen(navController = navController) } else { ProfileScreen(navController = navController) }
Что прекрасно работает. Проблема возникает, когда я пытаюсь петь в автоэкране:
when(val response = authViewModel.signInState.value) { is Response.Loading -gt; CircularProgressIndicator() is Response.Success -gt; { if (response.data) { navController.navigate("profile") Log.d(TAG, "Success") } } is Response.Error -gt; Log.d(TAG, response.message) }
Инструкция журнала печатает «Успех», но не переходит к следующему экрану профиля. Как это решить?
Комментарии:
1. Где вы поставили среднее условие «если бы»? Вы сами отображаете составные элементы здесь вместо того, чтобы переходить к ним и позволять NavController отображать их.
2. @ArpitShukla Я вставил оператор if
setContent
сразу после первого кода. Да, это то, что я делаю, я просто показываю эти экраны в соответствии с состоянием. Если я попытаюсь перейти к изменениюAuthScreen(navController = navController)
navController.navigate("auth")
, я получу NPE, указывающий на тоnavController.navigate("auth")
, где указано, что NavController равен нулю.3. Ах, классика. Это самая большая проблема навигации по реактивному ранцу, полностью игнорируемая Google. Невозможно изменить «корневой» экран, поэтому на вашем графике должна быть одна точка входа. Вам будет лучше использовать простой стек или вояджер, если на то пошло
Ответ №1:
Вы можете удалить это, если-еще из setContent
. Вместо этого сделайте ProfileScreen
в качестве домашнего пункта назначения, и внутри него вы сможете проверить, аутентифицирован пользователь или нет. Если это не так, перейдите к AuthScreen
@Composable fun ProfileScreen(navController: NavController) { LaunchedEffect(Unit) { if(!viewModel.isUserAuthenticated) { navController.navigate("auth") } } }
Если пользователь может выйти из системы с этого экрана (т. Е. состояние аутентификации может измениться), то вместо Unit
использования viewModel.isUserAuthenticated
в качестве ключа для LaunchedEffect
(при условии, что isUserAuthenticated
это a State
)
Комментарии:
1. Спасибо за ответ. Да, это штат. Позвольте мне попробовать.
2. Это работает, но есть одна проблема. Если пользователь не аутентифицирован, когда я запускаю приложение, оно отображает экран профиля, а сразу после этого-экран авторизации. Как сначала отобразить экран авторизации, не видя экран профиля? Я поддержал ваш ответ.
3. Когда вы устанавливаете значение этого логического значения? После
ProfileScreen
того, как будет запущен?4. В модели представления, которую я использую
val isUserAuthenticated get() = useCase.isUserAuthenticated()
. Что по умолчанию равно false, так как пользователь не аутентифицирован.5. Рад, что смог помочь 🙂