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

拆分messageId字符串转Long偶发NumberFormatException报错如何解决

问题原因

  • 直接原因:未对snapshot.key的格式做合法性校验,当出现不符合[senderId]_[timestamp]格式的key时(比如key不含下划线、下划线为全角字符、存在多个下划线、前后段格式颠倒),强行拆分取索引1的字段转Long就会抛出异常,你的报错就是因为取到的待转Long字段是纯字母的senderId字符串。
  • 隐含原因:使用LiveData的observe方法监听roomId列表,LiveData是粘性事件,每次触发回调(比如配置变更、roomId列表更新)时,都会给同一个roomId节点重复添加ChildEventListener,同一个消息会被多次回调处理,也会提升异常出现的概率,同时还会造成内存泄漏。

修复方案

1. 避免重复添加监听器

用容器保存已经绑定过监听器的roomId,避免重复绑定,页面销毁时统一移除所有监听器释放资源。

2. 增加格式校验

拆分messageId前先校验格式合法性,转Long时增加异常捕获,非法数据直接跳过处理不要强转强取。

修改后的代码示例

// 类内部添加HashMap保存已绑定的监听器
private val attachedListeners = hashMapOf<String, ChildEventListener>()

private fun insertMessage() {
    viewModel.readRoomIdFriendsDAO().observe(this, { listRoomId ->
        if (listRoomId != null && listRoomId.isNotEmpty()) {
            for (item in listRoomId) {
                // 已经绑定过监听器的roomId直接跳过
                if (attachedListeners.containsKey(item)) continue
                val messageListener = object : ChildEventListener {
                    override fun onChildAdded(snapshot:DataSnapshot,previousChildName: String?) {
                        val messageModel: MessageModel? = snapshot.getValue(MessageModel::class.java)
                        if (messageModel != null) {
                            val rawKey = snapshot.key?.trim() ?: return
                            messageModel.messageId = rawKey
                            messageModel.roomId = item
                            messageModel.uploadSuccess = true
                            // 拆分后先校验长度
                            val listTemp = rawKey.split("_")
                            if (listTemp.size >= 2) {
                                messageModel.messageSenderId = listTemp[0]
                                // 安全转Long,失败则跳过
                                runCatching {
                                    listTemp[1].trim().toLong()
                                }.onSuccess { timestamp ->
                                    messageModel.messageTimestamp = timestamp
                                    Log.e(TAG,"senderId: ${messageModel.messageSenderId}")
                                    Log.e(TAG,"timestamp: $timestamp")
                                    messageViewModel.insertMessageDAO(messageModel)
                                }.onFailure {
                                    Log.e(TAG, "时间戳格式非法,messageId:$rawKey", it)
                                }
                            } else {
                                Log.e(TAG, "messageId格式不合法,缺少下划线:$rawKey")
                            }
                        }
                    }
                    override fun onChildChanged(snapshot: DataSnapshot, previousChildName: String?) {}
                    override fun onChildRemoved(snapshot: DataSnapshot) {}
                    override fun onChildMoved(snapshot: DataSnapshot, previousChildName: String?) {}
                    override fun onCancelled(error: DatabaseError) {}
                }
                messageRef.child(item).addChildEventListener(messageListener)
                attachedListeners[item] = messageListener
            }
        }
    })
}

// 页面销毁时移除所有监听器
override fun onDestroy() {
    super.onDestroy()
    attachedListeners.forEach { (roomId, listener) ->
        messageRef.child(roomId).removeEventListener(listener)
    }
    attachedListeners.clear()
}

内容的提问来源于stack exchange,提问作者Lộc Trần Phước

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 17:24:01