我想在我的应用程序中实现一个多用户系统,有管理员用户,没有管理员用户.管理员用户可以在屏幕上看到一些其他用户看不到的功能.我正在try 使用Jetpack Compose和Firebase auth/FiRestore来做这件事,我使用了一个带有一些变量的UserData数据类,其中一个变量是"Role",我在这里输入了用户角色:"User"或"Admin".我不知道这是否是实施的最佳 Select ,欢迎提出建议.我在这里做的是在我的Use repo中添加一个Firebase Auth.AuthStateListener,当它发生变化时,如果用户不为空,我将签入Firebase角色并返回True或False,如果用户为空,则返回False.

(代码)

override fun getUserRole(viewModelScope: CoroutineScope) = callbackFlow {
    val authStateListener = FirebaseAuth.AuthStateListener { auth ->
        auth.currentUser?.uid?.let {
            usersRef.document(it).get().addOnSuccessListener { document ->
                if (document != null) {
                    val userRole = document.get("role").toString() == "ADMIN"
                    trySend(userRole)
                }
            }
        } ?: trySend(false)
    }
    auth.addAuthStateListener(authStateListener)
    awaitClose {
        auth.removeAuthStateListener(authStateListener)
    }
}.stateIn(viewModelScope, SharingStarted.WhileSubscribed(), false)

我不知道如何实现多用户系统,我试过了,需要帮助来做这件事.

我想实现的另一个规范是从FiRestore获取用户数据,我将需要所有应用程序中的数据,但我不想在每个视图模型中判断Auth.CurrentUser(如果是空的或不是..),并根据用户状态在每个视图模型中获取数据.我能做些什么呢?

谢谢!

推荐答案

当您想要跟踪身份验证状态时,确实必须使用AuthStateListener.每次用户的身份验证状态更改时,都会触发这样的监听程序.要判断用户是否已通过身份验证,则必须拨打FirebaseAuth#getCurrentUser():

返回当前登录的Firebase User,如果没有,则返回NULL.

这意味着您只需判断结果是否为无效:

val authStateListener = AuthStateListener { auth ->
    trySend(auth.currentUser == null)
}

因此,您的整个getUserRole函数应该如下所示:

override fun getUserRole(viewModelScope: CoroutineScope) = callbackFlow {
    val authStateListener = AuthStateListener { auth ->
        trySend(auth.currentUser == null) //?
    }
    auth.addAuthStateListener(authStateListener)
    awaitClose {
        auth.removeAuthStateListener(authStateListener)
    }
}.stateIn(viewModelScope, SharingStarted.WhileSubscribed(), auth.currentUser == null)
//                                                                 ?

现在,如果要判断FiRestore中的某个字段并基于现有值执行一些操作,则必须执行单独的操作.因此,在处理上述方法的结果的地方,当您收集结果并获得true(这意味着用户已通过身份验证)时,您必须立即执行FiRestore调用.根据你从FiRestore得到的结果,你可以采取进一步的行动.

在使用实际代码时,您会得到错误的结果,因为您假设当您正在判断的文档存在并且值role等于admin时,用户是经过身份验证的,这是一种错误的方法,因此会产生错误的结果.

为了简化一些事情,请注意,DocumentSnapshot#get(field: String)函数返回一个Any类型的对象.在这样的对象上调用toString()确实会返回该字段的值.但是,如果您已经知道role字段包含一个字符串,则应该考虑调用DocumentSnapshot#getString(field: String)函数,该函数:

以字符串形式返回字段的值.

因此,在您的用例中,代码可以简化为:

val userRole = document.getString("role") == "ADMIN"

Android相关问答推荐

房间数据库迁移未正确处理:原因:java.lang. IllegalState异常:

错误:无法解析Symbol@style/Theme. Androidstudio in AndroidManifest.html for Kotlin Android Development''

如何使禁用状态下的material 3按钮与启用状态下的 colored颜色 相同?

Jetpack编写Lazy列滑动删除动画不顺利结束

Jetpack Compose中的导航找不到NavHost类的名称为:startDestination";的参数

如何在Android Jetpack Compose中找到我的手机屏幕一行有多少个单词

MAP函数返回单位列表而不是字符列表

尽管我们不再使用GCM SDK,但应用程序已被标记为使用GCM SDK

OutlinedTextField仅显示一次

如何在DownloadManager Android中显示ProgressBar和Complete Listener

判断文本视图是否为单行

未解析的引用:视图模型

Android 中 recyclerview 的自定义分隔线 colored颜色 不起作用

返回并再次打开webview时webview无法打开相机

Kotlin - 在继续之前如何等待这个协程完成?

使用不同的gradle文件导入外部库

只能从同一个库组内调用成功(引用groupId=androidx.work from groupId=My Composable)

Kotlin Multiplatform Mobile targetSdk 已弃用

Android Transitions API - 在 24-48 小时后停止接收任何更新

如何在jetpack compose中创建自定义rememberState?