首页 > 解决方案 > Firebase:当数据实际到达 Firebase 数据库服务器时捕获事件

问题描述

我有一个聊天应用程序,它使用 FirebaseDatabase 传输和存储消息。聊天必须在手机在线或离线模式下工作(大多数聊天都是这样),因此消息具有三个状态值:“未发送”、“未读”和“已读”。
1.当消息组成时,它以“未发送”状态存储在本地。
2. 接下来我的应用实例尝试将其发送到 FirebaseDatabase 并在成功时将状态更改为“未读取”。
3. 最后,当合作伙伴收到消息时,他的应用实例在 FirebaseDatabase 上更新消息,状态为“已读”,而我的应用实例捕捉到此消息并更新本地消息数据。

当我尝试确定消息是否到达服务器以及何时更改其状态时,主要问题是第二步。

首先,我尝试发送一条消息:

private fun send (firebaseMessage: FirebaseMessage) {
   val ref = FirebaseDatabase.getInstance().getReference("/user-messages/${firebaseMessage.fromUid}/${firebaseMessage.toUid}/${firebaseMessage.Uid}")
   ref.setValue(firebaseMessage)
}

我有 childEventListener 如下:

private fun listen() {
    val ref = FirebaseDatabase.getInstance().getReference("/user-messages/${firebaseMessage.fromUid}/${firebaseMessage.toUid}")
    ref.addChildEventListener(object : ChildEventListener {
        override fun onCancelled(p0: DatabaseError) {}

        override fun onChildMoved(p0: DataSnapshot, p1: String?) {}

        override fun onChildChanged(p0: DataSnapshot, p1: String?) {
            updateMessage(p0.getValue(FirebaseMessage::class.java))
        }

        override fun onChildAdded(p0: DataSnapshot, p1: String?) {
            updateStatusMessage(p0.getValue(FirebaseMessage::class.java))
        }

        override fun onChildRemoved(p0: DataSnapshot) {}

    })
}

主要问题是 childEventListener 在子(新消息)简单地添加到 ref 之前触发 onChildAdded 方法,在它实际到达/与服务器同步之前且独立于它,即使手机处于离线状态,因此消息传递到服务器根本无法保证,所以我不能在 onChildAdded 方法中更改状态。

所以我需要:
1. 将消息状态设置为“未读”并将其发送到 FirebaseDatabase,然后捕获它到达服务器的事件,然后才以“未读”状态更新此消息的本地存储副本,
2 . 或者以某种方式在服务器端设置 FirebaseDatabase 以在到达时更改消息状态,然后此更改将被 onChildChanged 捕获,它将更新本地存储的此消息的副本,并具有“未读”状态。

标签: androidfirebasefirebase-realtime-databasekotlin

解决方案


当消息由服务器处理时,setValue调用返回完成。Task

ref.setValue(firebaseMessage).addOnSuccessListener {
    // Write was successful!
    // ...
}
.addOnFailureListener {
    // Write failed
    // ...
}

另请参阅有关添加完成回调的文档。


推荐阅读