You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

向Firebase Realtime Database发送消息后Android应用崩溃及聊天页面持续闪退问题求助

解决Firebase Realtime Database转换ChatMessage时的崩溃问题

Hey,我来帮你拆解下这个崩溃的原因和解决办法:

错误核心原因

从错误日志Can't convert object of type java.lang.String to type com.example.gesit.ChatMessage可以明确:你的代码尝试把Firebase数据库里的一个字符串类型数据,转换成自定义的ChatMessage实体类,类型不匹配直接导致了崩溃

出现这种情况通常有两个可能:

  • 数据库中存在不符合ChatMessage结构的节点:比如某个子节点不是包含idtextfromId等字段的对象,而是直接的字符串值(你提到删除对应消息就能恢复,说明这个出问题的消息节点确实是不符合结构的)。
  • 消息写入逻辑有疏漏:比如写入时没有用push()生成独立节点,误将字符串直接写入了消息路径下,而非嵌套的对象结构。

解决方案

1. 先修复当前数据库的问题

登录Firebase控制台,找到pesan-pengguna节点下对应的fromId/toId路径,检查所有子节点:

  • 删除任何不是ChatMessage结构的节点(比如直接的字符串值),确保每个子节点都是包含idtextfromIdtoIdtimestamp字段的对象。

2. 给读取代码添加异常防护,避免后续崩溃

即使以后再出现错误数据,也不能让Activity直接崩溃,在onChildAdded方法里加上try-catch块:

override fun onChildAdded(snapshot: DataSnapshot, previousChildName: String?) {
    try {
        val chatMessage = snapshot.getValue(ChatMessage::class.java)
        chatMessage?.let {
            Log.d(TAG, it.text)
            if (it.fromId == FirebaseAuth.getInstance().uid) {
                MainScreen.currentUser?.let { currentUser ->
                    adapter.add(ChatItemRight(it.text, currentUser))
                }
            } else {
                toUser?.let { targetUser ->
                    adapter.add(ChatItemLeft(it.text, targetUser))
                }
            }
        }
    } catch (e: DatabaseException) {
        Log.e(TAG, "解析消息失败,无效数据:${snapshot.value}", e)
        // 这里可以加个Toast提示用户有无效消息,或者仅记录日志
    }
}

3. 确保消息写入逻辑正确

检查你的消息发送代码,必须用push()生成唯一的节点ID,并且写入完整的ChatMessage对象,示例代码如下:

private fun sendMessage(messageText: String) {
    val currentUserId = FirebaseAuth.getInstance().uid ?: return
    val targetUserId = toUser?.uid ?: return

    // 写入当前用户的消息列表
    val userMessageRef = FirebaseDatabase.getInstance()
        .getReference("/pesan-pengguna/$currentUserId/$targetUserId")
        .push()
    val chatMessage = ChatMessage(
        id = userMessageRef.key!!,
        text = messageText,
        fromId = currentUserId,
        toId = targetUserId,
        timestamp = System.currentTimeMillis() / 1000
    )
    userMessageRef.setValue(chatMessage)

    // 同时写入对方的消息列表(双向同步)
    val targetMessageRef = FirebaseDatabase.getInstance()
        .getReference("/pesan-pengguna/$targetUserId/$currentUserId")
        .push()
    targetMessageRef.setValue(chatMessage)
}

4. 确认ChatMessage类的序列化正确性

你的ChatMessage类已经有了无参构造函数,这是Firebase反序列化必须的,这块没问题,但可以确保所有字段都是可访问的(Kotlin默认是public,所以不用额外修改):

class ChatMessage(
    val id: String,
    val text: String,
    val fromId: String,
    val toId: String,
    val timestamp: Long
) {
    // Firebase反序列化需要的无参构造函数
    constructor() : this("","","","", -1)
}

内容的提问来源于stack exchange,提问作者Tommy -

火山引擎 最新活动