Android使用Voyager导航库处理登录后返回键异常问题
Voyager导航库登录跳转后返回栈问题
我在Android应用中使用Voyager导航库(版本1.0.0),遇到登录页跳转首页后的导航问题:
login screen ==> home screen
用户登录成功后,需要从导航栈中移除登录页,避免返回时回到登录页,但按系统返回键仍会回到登录页。
现有代码
LoginScreenRoute代码
object LoginScreenRoot : Screen { @Composable override fun Content() { val loginViewModel = koinViewModel<LoginViewModel>() val navigator = LocalNavigator.currentOrThrow LoginScreen( loginState = loginViewModel.loginState, onLoginAction = loginViewModel::loginAction, onLoginSuccess = { /** Navigate to the home screen */ Timber.d("onLoginSuccess") navigator.popAll() // Try and pop the LoginScreen so we do go back to it navigator.push(HomeScreenRoute) }, onLoginFailure = { /** Display message */ Timber.d("onLoginFailure") }, onForgotPassword = { /** Navigate to the home screen */ Timber.d("onForgotPassword") navigator.push(ResetScreenRoute) } ) } }
HomeScreen代码
object HomeScreenRoute : Screen { @Composable override fun Content() { val homeViewModel = koinViewModel<HomeViewModel>() val homeState = homeViewModel.homeState val navigator = LocalNavigator.currentOrThrow HomeScreen( onForwardButtonClicked = { navigator.push(SurveyStartScreenRoute) }, homeState = homeState ) } }
MainActivity代码
setContent { BusbySurveyTheme { val scope = rememberCoroutineScope() if(mainViewModel.mainState.isLoggedIn) { Navigator(screen = HomeScreenRoute) } else { GradientBackground { Navigator(screen = LoginScreenRoot) } } } }
问题原因与解决方案
问题根源
你当前用navigator.popAll() + navigator.push()的方式存在逻辑问题:Voyager的popAll()会清空整个导航栈,之后Navigator会自动回到初始设置的LoginScreenRoot,再执行push(HomeScreenRoute)后,栈内实际是[LoginScreenRoot, HomeScreenRoute],所以按返回键会回到登录页。
同时MainActivity中根据登录状态创建不同Navigator实例的做法,会导致两个独立的导航栈,状态同步容易出问题。
修正步骤
修改登录成功后的导航逻辑
替换popAll()+push()为replaceAll(),直接清空栈并设置首页为根页面:onLoginSuccess = { Timber.d("onLoginSuccess") // 更新全局登录状态(需确保mainViewModel的状态是可观察的,比如用StateFlow) mainViewModel.updateLoggedInState(true) // 替换整个导航栈为首页,彻底移除登录页 navigator.replaceAll(HomeScreenRoute) }统一Navigator实例
MainActivity中只创建一个Navigator,根据登录状态设置初始页面,避免多个导航栈冲突:setContent { BusbySurveyTheme { val mainState by mainViewModel.mainState.collectAsState() val initialScreen = if (mainState.isLoggedIn) { HomeScreenRoute } else { LoginScreenRoot } Navigator(screen = initialScreen) } }确保登录状态可观察
在MainViewModel中用StateFlow维护登录状态,确保Compose能感知状态变化:// MainViewModel示例代码 data class MainState(val isLoggedIn: Boolean) private val _mainState = MutableStateFlow(MainState(isLoggedIn = false)) val mainState = _mainState.asStateFlow() fun updateLoggedInState(isLoggedIn: Boolean) { _mainState.value = _mainState.value.copy(isLoggedIn = isLoggedIn) }
这样修改后,登录成功后导航栈仅保留首页,按返回键会直接退出应用,同时重启应用时会根据登录状态直接进入对应页面。
内容的提问来源于stack exchange,提问作者ant2009
相关产品推荐
相关产品推荐

