如何在Jetpack Compose中基于登录状态实现条件嵌套导航
在Jetpack Compose中实现基于Room的认证状态校验与条件导航
1. 定义导航路由
首先用密封类统一管理导航页面的路由,方便后续跳转控制:
sealed class Screen(val route: String) { object Splash : Screen("splash") // 状态加载过渡页 object Login : Screen("login") // 未登录时的登录页 object Home : Screen("home") // 已登录后的主页 }
2. 核心导航逻辑实现
在导航宿主组件中,通过collectAsState监听SessionManager的状态变化,根据状态自动跳转对应页面:
@Composable fun MainNavigation(sessionManager: SessionManager) { val navController = rememberNavController() val sessionState by sessionManager.sessionState.collectAsState() NavHost(navController = navController, startDestination = Screen.Splash.route) { // 过渡加载页 composable(Screen.Splash.route) { SplashScreen() // 监听状态变化,触发导航 LaunchedEffect(sessionState) { when (sessionState) { SessionState.Loading -> { // 保持在过渡页,等待状态加载完成 } SessionState.Active -> { navController.navigate(Screen.Home.route) { // 清除回退栈,避免返回过渡页或登录页 popUpTo(Screen.Splash.route) { inclusive = true } } } SessionState.InActive -> { navController.navigate(Screen.Login.route) { popUpTo(Screen.Splash.route) { inclusive = true } } } } } } // 登录页 composable(Screen.Login.route) { LoginScreen( onLoginSuccess = { // 登录成功后更新会话状态 sessionManager.updateSession(SessionState.Active) } ) } // 主页 composable(Screen.Home.route) { HomeScreen( onLogout = { // 登出后更新会话状态 sessionManager.updateSession(SessionState.InActive) } ) } } }
3. 完善SessionManager的状态更新能力
你的现有代码只处理了初始状态加载,需要补充登录/登出后的状态同步逻辑,同时修复异常处理(避免直接抛异常导致崩溃):
class SessionManager( private val sessionRepo: SessionRepository, private val coroutineScope: CoroutineScope ) { private val _sessionState = MutableStateFlow(SessionState.Loading) val sessionState: StateFlow<SessionState> = _sessionState init { coroutineScope.launch { sessionRepo.getActiveSession() .collect { resource -> _sessionState.value = when (resource) { is Resource.Success -> { if (resource.data == null) SessionState.InActive else SessionState.Active } is Resource.Error -> { // 加载失败默认设为未登录状态,避免崩溃 SessionState.InActive } is Resource.Loading -> SessionState.Loading } } } } // 登录/登出时调用,同步Room数据与状态流 fun updateSession(newState: SessionState) { coroutineScope.launch { when (newState) { SessionState.Active -> sessionRepo.saveActiveSession(/* 传入会话数据 */) SessionState.InActive -> sessionRepo.clearActiveSession() SessionState.Loading -> {} // 无需处理 } // 触发重新加载会话,确保状态流与Room数据同步 sessionRepo.getActiveSession().first() } } }
4. 简单实现过渡加载页
@Composable fun SplashScreen() { Box( modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center ) { CircularProgressIndicator() } }
可选:处理错误状态
如果需要更精细的错误处理,可以扩展SessionState增加错误类型:
sealed class SessionState { object Loading : SessionState() object Active : SessionState() object InActive : SessionState() data class Error(val message: String) : SessionState() }
然后在状态收集和导航逻辑中添加错误分支的处理(比如显示错误提示后跳转到登录页)。
内容的提问来源于stack exchange,提问作者Emmanuel Mtali
相关产品推荐
相关产品推荐

