我有这些屏幕:
NavHost(
navController = navController,
startDestination = AuthScreen.route
) {
composable(
route = AuthScreen.route
) {
AuthScreen()
}
composable(
route = MainScreen.route
) {
MainScreen()
}
}
在MainActivity中,我需要根据身份验证状态将用户发送到正确的屏幕。所以我用:
val isUserSignedOut = viewModel.getAuthState().collectAsState().value
if (isUserSignedOut) {
navController.navigate(AuthScreen.route) {
popUpTo(navController.graph.id) {
inclusive = true
}
}
} else {
navController.navigate(MainScreen.route) {
popUpTo(navController.graph.id) {
inclusive = true
}
}
}
一切都按预期进行,因为我认为这是一个同步操作。现在,当用户通过身份验证时,我需要创建一个请求来检查用户的类型。这是我尝试过的:
if (isUserSignedOut) {
navController.navigate(AuthScreen.route) {
popUpTo(navController.graph.id) {
inclusive = true
}
}
} else {
Request(
checkAdmin = { admin ->
if (admin) {
navController.navigate(AdminScreen.route) {
popUpTo(navController.graph.id) {
inclusive = true
}
}
} else {
navController.navigate(MainScreen.route) {
popUpTo(navController.graph.id) {
inclusive = true
}
}
}
}
)
}
此代码的问题是,当我打开应用程序时,即使用户已通过身份验证,我第一次也会显示
AuthScreen
。换句话说,当我收到异步请求的响应时,会显示 AuthScreen
,但我不希望这样。我需要先转到 MainScreen
或 AdminScreen
,而不显示 AuthScreen
。怎么解决这个问题?
您可能这样声明
isUserSignedOut
:
var isUserSignedOut by remember { mutableStateOf(true) }
这会将变量初始化为 true。这将导致立即显示 AuthScreen。
你必须引入第三种状态:
当App执行异步请求时,将状态设置为“正在加载”,然后显示一个正在加载的Composable。
您必须选择执行此操作:
A) 您可以创建第二个布尔变量:
var isLoading by remember { mutableStateOf(true) }
然后将您的条件更新为
if (isLoading) {
// show or navigate to Loading Screen Composable
} else if (isUserSignedOut) {
navController.navigate(AuthScreen.route) {
popUpTo(navController.graph.id) {
inclusive = true
}
}
} else {
Request(
checkAdmin = { admin ->
if (admin) {
navController.navigate(AdminScreen.route) {
popUpTo(navController.graph.id) {
inclusive = true
}
}
} else {
navController.navigate(MainScreen.route) {
popUpTo(navController.graph.id) {
inclusive = true
}
}
}
}
)
}
异步操作完成后,执行
isLoading = false
。
B) 您可以创建一个枚举来表示不同的状态:
enum class UIState{
LOADING, LOGGEDIN, NOTLOGGEDIN
}
在您的可组合项中:
var uiState by remember { mutableStateOf(UISTATE.LOADING) }
if (uiState.equals(UIState.LOADING) {
//...
} else if (uiState.equals(UIState.NOTLOGGEDIN) {
//...
} else {
//...
}