我想在我的应用程序中实现一个多用户系统,有管理员用户,没有管理员用户.管理员用户可以在屏幕上看到一些其他用户看不到的功能.我正在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相关问答推荐

Android配置设置. gradle不同应用风格

如何阻止Gradle在编译时生成app-metadata.properties

如何从Android 12的来电中获取电话号码?

jetpackcompose-如何对解析后的复杂对象进行状态提升?

更改活动(上下文)对接收到的uri的访问权限的影响?

expo 上的 socket.io 无法从 Android 连接

减少Compose中可滚动选项卡之间的间距

如何使用滑行加载媒体的专辑封面?

如何在Android中使用嵌套的Recyclerview

appcompat 依赖从何而来?

java.lang.ExceptionInInitializerError -- 原因:java.lang.NullPointerException

Jetpack compose (Glance) 小部件在加载位图图像后不会重新组合

在 Jetpack Compose 中使用 ViewModel 实现 startActivity 的最佳实践

在 Jetpack Compose 中使用 .observeAsState() 时,如何在更改 MutableLiveData 的值后开始执行一段代码?

组成不重叠的元素

新的内部测试应用程序版本不适用于测试人员,即使它说它们是

构成material 3 中的分隔符

Kotlin Compose 全局页脚视图

react-native android项目未找到错误

(Android) 如何在一对多关系中将子 ID 与父级匹配