当有唯一键 Kotlin 时如何从 Firebase 检索孩子

Posted

技术标签:

【中文标题】当有唯一键 Kotlin 时如何从 Firebase 检索孩子【英文标题】:How to retrieve a child from Firebase when there is a unique key Kotlin 【发布时间】:2020-08-08 11:24:20 【问题描述】:

我想从 Firebase 实时数据库中检索特定的子值,例如(电话号码、名字、姓氏) 但是每个用户都有一个唯一的密钥

这就是树:

我试过了:

    var loginRef = rootRef.child("users").orderByChild("phoneNumber").equalTo(phone).addListenerForSingleValueEvent(
        object : ValueEventListener 
        override fun onDataChange(dataSnapshot: DataSnapshot) 
            // Get data object and use the values to update the UI
            val phoneNumber = dataSnapshot.getValue<User>()!!.phoneNumber
            // ...
            Toast.makeText(applicationContext, "phone number is: $phoneNumber", Toast.LENGTH_LONG).show()

        

        override fun onCancelled(databaseError: DatabaseError) 
            // Getting Data failed, log a message
            Log.w(TAG, "LoginData:onCancelled", databaseError.toException())
            // ...
            Toast.makeText(applicationContext, "error", Toast.LENGTH_LONG).show()
        
    )

我有一个名为 User 的简单模型来处理数据(我知道密码应该在这里散列)

@IgnoreExtraProperties
data class User(
    var firstName: String? = "",
    var fatherName: String? = "",
    var familyName: String? = "",
    var phoneNumber: String? = "",
    var password: String? = ""
) 

    @Exclude
    fun toMap(): Map<String, Any?> 
        return mapOf(
            "firstName" to firstName,
            "fatherName" to fatherName,
            "familyName" to familyName,
            "phoneNumber" to phoneNumber,
            "password" to password
        )
    

dataSnapshot.getValue&lt;User&gt;()!!.phoneNumber 永远不会起作用,因为在此查询中检索到的第一个节点是唯一键

我需要为我想要使用的每个孩子提供类似dataSnapshot.child("unique-key/phoneNumber").value 的东西,但比为每个节点创建.addChildEventListener 更容易和更有效

【问题讨论】:

【参考方案1】:

让我们先对代码做一些注释:

您需要注意的第一件事是:

dataSnapshot.getValue&lt;User&gt;()!!.phoneNumber

因为如果 phoneNumber 不存在,它可能为 null 并且会抛出错误。

其次,假设你做了一些空处理,它仍然会检索你的空字符串,因为你发送给模型的只是唯一键,当然你不能用这个模型处理它。

解决此问题并获取检索到的节点的子节点的最简单方法是根据此解决方案使用 for 循环:https://***.com/a/38652274/10324295

你需要让 for 循环将每个项目放入一个数组列表中,试试这个代码:

    val userList: MutableList<User?> = ArrayList()
    var loginRef = rootRef.child("users").orderByChild("phoneNumber").equalTo(phone).addListenerForSingleValueEvent(
        object : ValueEventListener 
            override fun onDataChange(dataSnapshot: DataSnapshot) 
                userList.clear()
                for (userSnapshot in dataSnapshot.children) 
                    val user: User? = userSnapshot.getValue(User::class.java)
                    userList.add(user)

                    // Get Data object and use the values to update the UI
                    // ...
                    Toast.makeText(applicationContext, "hi: $user!!.phoneNumber", Toast.LENGTH_LONG).show()
                

            
            override fun onCancelled(databaseError: DatabaseError) 
                // Getting Data failed, log a message
                Log.w(TAG, "LoginData:onCancelled", databaseError.toException())
                // ...
                Toast.makeText(applicationContext, "error", Toast.LENGTH_LONG).show()
            
        )

【讨论】:

【参考方案2】:
var loginRef = rootRef.child("users").orderByChild("phoneNumber").equalTo(phone).addListenerForSingleValueEvent(
        object : ValueEventListener 
        override fun onDataChange(dataSnapshot: DataSnapshot) 
            // retreive all children firstly by foreach
            dataSnapshot.children.forEach  data ->
              val userModel = data.getValue(User::class.java)
              val phoneNumber = userModel!!.phoneNumber
              Toast.makeText(applicationContext, "phone number is: $phoneNumber", 
              Toast.LENGTH_LONG).show()
            
            // ...


        

        override fun onCancelled(databaseError: DatabaseError) 
            // Getting Data failed, log a message
            Log.w(TAG, "LoginData:onCancelled", databaseError.toException())
            // ...
            Toast.makeText(applicationContext, "error", 
            Toast.LENGTH_LONG).show()
        
    )

【讨论】:

以上是关于当有唯一键 Kotlin 时如何从 Firebase 检索孩子的主要内容,如果未能解决你的问题,请参考以下文章

当有两个 gpu 时,如何设置 Torch 只使用一个 gpu?

如何从 kotlin 中的 firestore 读取映射数据

如何避免没有主键和唯一键的重复条目?

如何从字典列表中查找唯一键值以创建新列表

在谷歌地图 V2 android studio 中单击 InfoWindowClick 时,如何设置唯一键?

Kotlin 多平台注释处理