Jetpack Compose Navigation中startDestination异常,始终显示登录界面怎么修复?
用户编写了如下Compose导航代码,逻辑上可行,但实际运行时用户始终看到登录界面,需要修复:
@Composable fun RootNav() { val navController = rememberNavController() val authViewModel: AuthViewModel = hiltViewModel() val authState by authViewModel.authState.collectAsState() val startDestination = when (authState) { is AuthState.Unauthenticated -> ScreenRoutes.AuthNav.route is AuthState.AuthenticatedWithoutCouple -> ScreenRoutes.RegisterNav.route is AuthState.AuthenticatedWithCouple -> ScreenRoutes.HomeNav.route else -> ScreenRoutes.AuthNav.route } NavHost( navController = navController, startDestination = startDestination ) { AuthNav(authViewModel, navController) RegisterNav(navController) composable(route = ScreenRoutes.HomeNav.route) { HomeNavGraph(navController){ authViewModel.signOut() } } } }
修复方案
1. 修正AuthState的初始值与初始化逻辑
问题根源之一可能是AuthState的初始值未正确设置,且ViewModel未在启动时主动检查用户登录状态。默认初始值如果是Unauthenticated,会直接导向登录页,后续即使异步获取到用户状态,也不会触发导航更新。
修改AuthViewModel,添加初始加载状态,并在初始化时检查当前用户:
class AuthViewModel @Inject constructor( private val authRepository: AuthRepository ) : ViewModel() { // 初始设为Loading状态,避免直接进入登录页 private val _authState = MutableStateFlow<AuthState>(AuthState.Loading) val authState = _authState.asStateFlow() init { // 启动时立即检查用户认证状态 checkCurrentAuthStatus() } private fun checkCurrentAuthStatus() { viewModelScope.launch { val currentUser = authRepository.getCurrentUser() _authState.value = when { currentUser == null -> AuthState.Unauthenticated authRepository.hasCoupleInfo(currentUser.id) -> AuthState.AuthenticatedWithCouple else -> AuthState.AuthenticatedWithoutCouple } } } }
2. 动态监听AuthState变化,替换静态startDestination
原代码中startDestination仅在NavHost初始化时计算一次,后续authState更新不会触发导航变更。需要用LaunchedEffect监听状态变化,动态导航到对应页面:
修改RootNav代码:
@Composable fun RootNav() { val navController = rememberNavController() val authViewModel: AuthViewModel = hiltViewModel() val authState by authViewModel.authState.collectAsState() // 监听authState变化,动态调整导航 LaunchedEffect(authState) { val targetRoute = when (authState) { AuthState.Loading -> return@LaunchedEffect // 加载状态不跳转 is AuthState.Unauthenticated -> ScreenRoutes.AuthNav.route is AuthState.AuthenticatedWithoutCouple -> ScreenRoutes.RegisterNav.route is AuthState.AuthenticatedWithCouple -> ScreenRoutes.HomeNav.route } // 避免重复导航,减少不必要的页面栈操作 if (navController.currentDestination?.route != targetRoute) { navController.navigate(targetRoute) { popUpTo(navController.graph.startDestinationId) { inclusive = true } } } } NavHost( navController = navController, startDestination = ScreenRoutes.Loading.route // 初始显示加载页 ) { // 新增加载页,给用户明确的加载反馈 composable(ScreenRoutes.Loading.route) { LoadingScreen() // 自定义简单的加载UI,比如CircularProgressIndicator } AuthNav(authViewModel, navController) RegisterNav(navController) composable(route = ScreenRoutes.HomeNav.route) { HomeNavGraph(navController){ authViewModel.signOut() } } } }
3. 验证登录成功后的状态更新
确保用户登录成功时,AuthViewModel正确更新authState为AuthenticatedWithoutCouple或AuthenticatedWithCouple,触发LaunchedEffect的导航逻辑。例如登录方法:
fun login(email: String, password: String) { viewModelScope.launch { val result = authRepository.login(email, password) if (result.isSuccess) { checkCurrentAuthStatus() // 登录成功后重新检查状态,更新authState } else { // 处理登录失败逻辑 } } }
内容的提问来源于stack exchange,提问作者Talha K.
相关产品推荐
相关产品推荐

