我有这些屏幕:

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
        }
    }
}

一切都按预期进行,因为我认为这是一个同步操作.现在,当用户通过身份验证时,我需要创建一个请求来判断用户类型.以下是我try 过的:

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,我不希望这样.我需要go MainScreenAdminScreen没有显示AuthScreen第一.如何解决这个问题?


编辑:

@BenjyTec我从ViewModel获取auth状态:

fun getAuthState() = authRepo.getAuthState(viewModelScope)

以下是回购计划:

override fun getAuthState(viewModelScope: CoroutineScope) = callbackFlow {
    val listener = FirebaseAuth.AuthStateListener { auth ->
        trySend(auth.currentUser == null)
    }
    auth.addAuthStateListener(listener)
    awaitClose {
        auth.removeAuthStateListener(listener)
    }
}.stateIn(
    scope = viewModelScope,
    started = SharingStarted.WhileSubscribed(),
    initialValue = auth.currentUser == null
)

推荐答案

您可以这样声明流的初始值:

initialValue = auth.currentUser == null

所以在异步回调完成之前,你的isUserSignedOut就已经是true了.因此,AuthScreen将立即显示.

你将不得不引入第三种状态:

  • 用户已登录
  • 用户未登录
  • 装载量

当App执行异步请求时,最初将状态设置为"正在加载",然后显示一个正在加载的Composable.

您可以创建一个枚举来表示不同的州:

enum class UIState{
    LOADING, LOGGEDIN, NOTLOGGEDIN
}

然后像这样声明您的流程:

override fun getAuthState(viewModelScope: CoroutineScope) = callbackFlow {
    val listener = FirebaseAuth.AuthStateListener { auth ->
        if (auth.currentUser == null) {
            trySend(UIState.NOTLOGGEDIN)
        } else {
            trySend(UIState.LOGGEDIN)
        }
    }
    auth.addAuthStateListener(listener)
    awaitClose {
        auth.removeAuthStateListener(listener)
    }
}.stateIn(
    scope = viewModelScope,
    started = SharingStarted.WhileSubscribed(),
    initialValue = UIState.LOADING
)

在你的Composable中:

var uiState by viewModel.getAuthState().collectAsState()

if (uiState.equals(UIState.LOADING) {
    // show loading Composable
} else if (uiState.equals(UIState.NOTLOGGEDIN) {
    // navigate to AuthScreen Composable
} else {
   // navigate to MainScreen Composable
}

或在下列情况下使用:

when (uiState) {
    UIState.LOADING -> {/** show loading Composable **/}
    UIState.NOTLOGGEDIN -> {/** navigate to AuthScreen Composable **/}
    UIState.LOGGEDIN -> { /** navigate to MainScreen Composable **/ }
}

Android相关问答推荐

如何完全隐藏的元素堆叠在CardView?

list 合并失败,AGP 8.3.0

RemoteActivityHelper.startRemoteActivity不适用于Android Wear OS 4模拟器

fillMaxHeight中的分数在列内不起作用(android jetpack compose)

Jetapck Compose:将Compose BOM更新为最新版本&2024.01.00&Quot;CircularProgressIndicator后出现错误

在模块中找到重复的类com.google.Firebase.auth.ktx.AuthKt||Android Studio

从未设置实时数据值

在Android中使用Room从SQlite数据库中获取实体列表的正确方式是什么?

可以';t将数据插入房间数据库

Android Kotlin - 计费 - 从应用内购买获取productId

如何在Android Studio中禁用文件中的Github用户名引用?

在 Android 房间迁移中获取上下文

从 HiltViewModel @Injection 访问 Application()

如何知道我的应用程序的新版本是否显示广告?

Jetpack Compose 中的滑动按钮菜单

Jetpack Compose Arc 进度条动画(如何重启动画)

LazyColumn 单选中的状态提升. Jetpack compose

我们也可以或应该对主要小部件使用预览 compose 功能吗?

Android 自动分页如何与 media3 配合使用?

Android YouTube SDK - 视频无法在某些 Android 设备中播放