解决Firebase DatabaseException:ArrayList转WaitUserModel失败问题
异常信息
com.google.firebase.database.DatabaseException: 无法将java.util.ArrayList类型的对象转换为com.example.myapplication.WaitUserModel类型
at com.google.firebase.database.core.utilities.encoding.CustomClassMapper.convertBean(CustomClassMapper.java:436)
at com.google.firebase.database.core.utilities.encoding.CustomClassMapper.deserializeToClass(CustomClassMapper.java:232)
at com.google.firebase.database.core.utilities.encoding.CustomClassMapper.convertToCustomClass(CustomClassMapper.java:80)
at com.google.firebase.database.DataSnapshot.getValue(DataSnapshot.java:203)
at com.example.myapplication.CategoryPage$startMatching$1$onDataChange$1.onDataChange(CategoryPage.kt:150)
...(省略中间栈信息)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
相关代码
WaitUserModel.kt
data class WaitUserModel( val uid: String, var grade: Float?, var brands: ArrayList<String>, var fail: Int = 0 ) { init { // 将字符串解析为浮点型并存储到grade字段 this.grade = grade ?: 0.0f } }
CategoryPage.kt关键代码(startMatching方法)
fun startMatching(selectedBrands: MutableList<String>) { // ...省略前面代码 // 查找匹配等待中的用户 waitUsersRef.addListenerForSingleValueEvent(object : ValueEventListener { override fun onDataChange(snapshot: DataSnapshot) { for (waitUserSnapshot in snapshot.children) { val waitUser = waitUserSnapshot.getValue(WaitUserModel::class.java) if (waitUser != null && waitUser.uid != currentUserId && waitUser.brands != null) { // 手动转换brands字段 val brands = waitUserSnapshot.child("brands").getValue() as? ArrayList<String> waitUser.brands = (brands ?: ArrayList()) val intersection = waitUser.brands.intersect(mySelectedBrands) if (intersection.isNotEmpty()) { // ...省略匹配逻辑 } } } } override fun onCancelled(error: DatabaseError) {} }) // ...省略其他代码 }
Firebase数据库WaitUsers节点结构
"gLXAaWKYGTdPzceWbrqcQBSA67C3": { "brands": [ "비비큐", "지코바" ], "fail": 0, "grade": 0, "uid": "gLXAaWKYGTdPzceWbrqcQBSA67C3" }
1. 修改WaitUserModel的集合类型与构造函数
Firebase反序列化时默认将数组转为java.util.ArrayList,但Kotlin中使用集合接口而非具体实现类能避免类型冲突。同时必须添加无参构造函数(Firebase反序列化的强制要求):
data class WaitUserModel( val uid: String, var grade: Float?, var brands: List<String>, // 改为List接口,适配Firebase自动转换 var fail: Int = 0 ) { init { this.grade = grade ?: 0.0f } // 添加无参构造函数 constructor() : this("", 0.0f, emptyList()) }
2. 删除冗余的手动转换代码
修改后Firebase会自动完成brands字段的反序列化,不需要手动获取并赋值,删除以下代码:
// 手动转换brands字段 -> 删除此行及后续赋值 val brands = waitUserSnapshot.child("brands").getValue() as? ArrayList<String> waitUser.brands = (brands ?: ArrayList())
3. 检查数据库节点完整性
确认WaitUsers节点下的所有子节点都是完整的WaitUserModel结构,不存在直接存储ArrayList的错误节点(比如误将brands数组直接存到WaitUsers根节点下)。
内容的提问来源于stack exchange,提问作者hahahahaya0624

