Android Firebase:当数据实际到达Firebase数据库服务器时捕获事件

Android Firebase:当数据实际到达Firebase数据库服务器时捕获事件,android,firebase,firebase-realtime-database,kotlin,Android,Firebase,Firebase Realtime Database,Kotlin,我有一个聊天应用程序,它使用FirebaseDatabase传输和存储消息。当手机处于在线或离线模式时,聊天功能必须正常工作(大多数聊天功能都是这样),因此信息有三个状态值:“未发送”、“未阅读”和“已阅读”。 1.当消息组成时,它以“未发送”状态本地存储。 2.下一步我的应用实例尝试将其发送到FirebaseDatabase,并在成功时将状态更改为“未读取”。 3.最后,当合作伙伴收到消息时,他的应用程序实例将FirebaseDatabase上的消息更新为“读取”状态,而我的应用程序实例将捕获

我有一个聊天应用程序,它使用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)
}
我有以下几点建议:

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将捕获此更改,它将使用“未读取”状态更新本地存储的此消息副本。

调用
setValue
返回一个
任务,该任务在服务器处理消息时完成

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

另请参阅上的文档。

但如果我尝试在ref.setValue(firebaseMessage.addOnSuccessListener{…}.addOnFailureListener{…}中以更新状态传递(firebaseMessage),它将首先被ref.onChildEventListener{onChildad(…)}捕获并写入本地存储,而实际上可能无法传递到服务器。而且我无法摆脱onChildEventListener,因为如果我关闭应用程序上的,它必须捕获其中的所有消息。本地事件会立即触发,这样你就可以更新UI了。如果您有一个用例要求您在数据提交到服务器(或在服务器上被拒绝)后执行某些操作,那么您应该使用完成处理程序。如果需要组合,可能必须在本地存储其他状态。