从Firebase实时数据库中使用Kotlin检索/获取嵌套节点对象

huangapple go评论65阅读模式
英文:

Retrieve/get nested node objects from firebase realtime using kotlin

问题

我想要从嵌套节点中获取数据对象(地址,签到时间,签退时间)。我的数据库结构如下:

---`attendance` :{
   |
   |---danielle:{ <---------- 这里是用户名,attendance节点
   |   |
   |   |---2023-04-08: <----------- 这里是她上下班签到和签退的日期
   |   |   |
   |   |   |---address: "Thomas street"
   |   |   |
   |   |   |---check_in: "09:02 AM"
   |   |   |
   |   |   |---check_out: "06:30 PM"
   |   |
   |   |
   |    ---2023-04-10":
   |       |
   |       |---address: "Maria street"
   |       |
   |       |---check_in: "09:02 AM"
   |       |
   |        ---check_out: "06:30 PM"
   |
    ---mark:{ <---------- 这是另一个用户名
       |
       |---2023-04-07: <----------- 这是他上下班签到和签退的日期
       |   |
       |   |---address: "Thomas street"
       |   |
       |   |---check_in: "09:02 AM"
       |   |
       |   |---check_out: "06:30 PM"
       |
       |
        ---2023-04-11":
           |
           |---address: "Maria street"
           |
           |---check_in: "10:23 AM"
           |
            ---check_out: "08:30 PM"          
       

你尝试使用以下代码:

val attModel = arrayListOf<AttendanceModel>()

Firebase.database.getReference("Attendance").child("danielle").child("2023-04-08").addValueEventListener(object : ValueEventListener {
                override fun onDataChange(snapshot: DataSnapshot) {
                    for (h in snapshot.children) {
                        val data = h.getValue(AttendanceModel::class.java)

                        attModel.add(data!!)

                    }
                }
            }

但是出现了以下错误:

Android : com.google.firebase.database.DatabaseException: Can't convert object of type java.lang.String to AttendanceModel

我明白danielle确实是一个字符串,但我不明白为什么会出现错误,因为danielle内部有一个对象节点。然后,你尝试嵌套访问2023-04-08路径的代码如下:

val todays = arrayListOf<AttendanceModel>()

Firebase.database.getReference("Attendance").child("danielle")
            .addValueEventListener(object : ValueEventListener {
                override fun onDataChange(snapshot: DataSnapshot) {
                    for (h in snapshot.children) {
                        val date = h.child("2023-04-08")
                        for (i in date.children) {
                            val dataUser = i.getValue(AttendanceModel::class.java)

                            todays.add(dataUser!!)
                        }
                    }
                }
            }

但在模拟器中没有返回任何数据,然后尝试记录dataUser,它返回:

DataSnapshot { key = danielle, value = null }

以下是你的数据类:

data class AttendanceModel(
    val loc_name: String? = "",
    val address: String? = "",
    val check_in: String? = "",
    val check_out: String? = ""
)

希望这能帮助你解决问题。

英文:

I want to get the data objects (address, check_in, check_out) from the date which is in the nested node.

My database goes by like this:


---`attendance` :{
   |
   |---danielle:{ <---------- here is username, node of `attendance`
   |   |
   |   |---2023-04-08: <----------- here is the date she checked in and out for work
   |   |   |
   |   |   |---address: "Thomas street"
   |   |   |
   |   |   |---check_in: "09:02 AM"
   |   |   |
   |   |   |---check_out: "06:30 PM"
   |   |
   |   |
   |    ---2023-04-10":
   |       |
   |       |---address: "Maria street"
   |       |
   |       |---check_in: "09:02 AM"
   |       |
   |        ---check_out: "06:30 PM"
   |
    ---mark:{ <---------- here is another username
       |
       |---2023-04-07: <----------- here is the date he checked in and out for work
       |   |
       |   |---address: "Thomas street"
       |   |
       |   |---check_in: "09:02 AM"
       |   |
       |   |---check_out: "06:30 PM"
       |
       |
        ---2023-04-11":
           |
           |---address: "Maria street"
           |
           |---check_in: "10:23 AM"
           |
            ---check_out: "08:30 PM"          
       

I tried to use this coding

val attModel = arrayListOf<AttendanceModel>()

Firebase.database.getReference("Attendance").child("danielle").child("2023-04-08").addValueEventListener(object : ValueEventListener {
                override fun onDataChange(snapshot: DataSnapshot) {
                    for (h in snapshot.children) {
                        val data = h.getValue(AttendanceModel::class.java)

                        attModel.add(data!!)

                    }
                }
            }

but i get this error

Android : com.google.firebase.database.DatabaseException: Can't convert object of type java.lang.String to AttendanceModel

I know danielle is indeed a String, but I don't understand how it can get an error because danielle has an object node inside.

I also tried this coding here where I tried to nest for the path 2023-04-08

val todays = arrayListOf<AttendanceModel>()

        Firebase.database.getReference("Attendance").child("danielle")
            .addValueEventListener(object : ValueEventListener {
                override fun onDataChange(snapshot: DataSnapshot) {
                    for (h in snapshot.children) {
                        val date = h.child("2023-04-08")
                        for (i in date.children) {
                            val dataUser = i.getValue(AttendanceModel::class.java)

                            todays.add(dataUser!!)
                        }

In emulator doesnt return anything, and then i tried to log dataUser, it gives me

DataSnapshot { key = danielle, value = null }

Here is my data class

data class AttendanceModel(
    val loc_name: String? = "",
    val address: String? = "",
    val check_in: String? = "",
    val check_out: String? = ""
)

Any kind of help would be so much appreciated!

答案1

得分: 0

不需要迭代快照的子项,因为已经获取了整个对象的日期。如果使用迭代,它将返回对象内每个键的值。

用以下方式替换:

val data = snapshot.getValue(AttendanceModel::class.java)
attModel.add(data!!)
英文:

No need iteration snapshot children because already entire object fetch for date. If we use iteration, it's will return value for each key which inside the object.

Replace

for (h in snapshot.children) {
val data = h.getValue(AttendanceModel::class.java)
 attModel.add(data!!)
 }

by

 val data = snapshot.getValue(AttendanceModel::class.java)
            attModel.add(data!!)

答案2

得分: 0

当您在2023-04-08上附加一个监听器时,无需进行迭代,您可以直接读取子节点的值,或者将该节点映射为AttendanceModel类型的对象。在代码中,它将如下所示:

val db = Firebase.database.reference
val dateRef = db.child("attendance/danielle/2023-04-08")
dateRef.get().addOnCompleteListener {
    if (it.isSuccessful) {
        val snapshot = it.result
        val key = snapshot.key
        Log.d(TAG, "key: $key")
        val data = snapshot.getValue(AttendanceModel::class.java)
        Log.d(TAG, "data: ${data.address}${data.check_in}/${data.check_out}")
    } else {
        Log.d(TAG, "${it.exception?.message}") // 永远不要忽略潜在的错误!
    }
}

在logcat中的结果将是:

key: 2023-04-08
data: Thomas street/09:02 AM/06:30 PM
英文:

When you attach a listener on the 2023-04-08, there is no need for an iteration, you can directly read the values of the children, or you can map the node into an object of type AttendanceModel. In code, it will be as simple as:

val db = Firebase.database.reference
val dateRef = db.child("attendance/danielle/2023-04-08")
dateRef.get().addOnCompleteListener {
	if (it.isSuccessful) {
        val snapshot = it.result
        val key = snapshot.key
        Log.d(TAG, "key: $key")
		val data = snapshot.getValue(AttendanceModel::class.java)
        Log.d(TAG, "data: ${data.address}${data.check_in}/${data.check_out}")
	} else {
		Log.d(TAG, "${it.exception?.message}") //Never ignore potential errors!
	}
}

The result in the logcat will be:

key: 2023-04-08
data: Thomas street/09:02 AM/06:30 PM

huangapple
  • 本文由 发表于 2023年4月10日 22:08:08
  • 转载请务必保留本文链接:https://go.coder-hub.com/75977827.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定