You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Kotlin中如何正确从Firebase实时数据库获取嵌套数据结构?

解决Firebase实时数据库类型转换异常的问题

首先直接点出问题根源:你遇到的com.google.firebase.database.DatabaseException: Failed to convert value of type java.util.HashMap to String错误,核心原因是你的User类里submittedRequests字段被定义成了String类型,但数据库中这个字段实际存储的是HashMap(或者列表/集合类结构),Firebase没法把哈希结构强转成字符串,自然就抛出崩溃了。

解决步骤

1. 先确认数据库实际结构

先去Firebase控制台查看submittedRequests的存储形式:

  • 如果是多个请求ID的集合(比如["req001", "req002"]),那它是字符串列表类型;
  • 如果是包含请求详情的键值对(比如{"req001": {"content": "代取快递"}, "req002": {"content": "帮忙买咖啡"}}),那它是哈希映射类型。

2. 修改User类的字段类型,匹配数据库结构

根据数据库的实际存储结构,调整User类的submittedRequests字段类型:

情况1:数据库里是字符串列表(请求ID集合)

把字段改成List<String>并设置默认空列表:

class User(
    val userId: String = "", 
    val name: String = "", 
    val surname: String = "", 
    val profileImageUrl: String = "",
    val submittedRequests: List<String> = emptyList(), 
    val pickedUpRequests: String = "" // 如果这个字段也存在同样问题,记得同步调整
)

情况2:数据库里是请求对象的哈希映射

先定义一个对应请求结构的数据类(根据你的实际字段调整):

data class Request(
    val requestId: String = "",
    val requestContent: String = "",
    val createTime: Long = 0 // 示例字段,按数据库实际内容添加
)

再把User类里的submittedRequests改成Map<String, Request>:

class User(
    val userId: String = "", 
    val name: String = "", 
    val surname: String = "", 
    val profileImageUrl: String = "",
    val submittedRequests: Map<String, Request> = emptyMap(), 
    val pickedUpRequests: String = ""
)

3. 额外注意事项

  • 如果数据库字段名和类里的驼峰命名不一致(比如数据库是submitted_requests,类里是submittedRequests),需要添加@PropertyName注解做映射:
    @PropertyName("submitted_requests")
    val submittedRequests: List<String> = emptyList()
    
  • 确保数据类都有默认值(你现在已经设置了,这点没问题),Firebase需要空参构造能力来解析数据。

4. 原获取代码无需大幅修改

调整完User类后,你原来的监听代码可以直接使用,Firebase会自动把数据库结构解析成你定义的类对象:

userRef.addValueEventListener(object : ValueEventListener {
    override fun onCancelled(p0: DatabaseError) {
        // 建议添加错误日志,方便后续排查问题
        Log.e("FirebaseError", "数据获取失败: ${p0.message}")
    }
    override fun onDataChange(snapshot: DataSnapshot) {
        if(snapshot.exists()){
            val children = snapshot.children
            userData.clear() // 先清空旧数据,避免重复添加
            for(item in children) {
                val retrieveUser = item.getValue(User::class.java)
                retrieveUser?.let { userData.add(it) }
            }
            // 此处可通知UI更新数据
        }
    }
})

内容的提问来源于stack exchange,提问作者Kadir Saglam

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 10:47:27