【问题标题】:Firebase get wrong data [duplicate]Firebase得到错误的数据[重复]
【发布时间】:2019-12-17 21:55:50
【问题描述】:

我正在开发一个聊天应用程序并使用 firebase 作为后端服务。我使用snapshot.exists() 来检查孩子是否存在并做一些事情。但是即使那个孩子不存在,Firebase 也会返回 true。示例:我有 2 个用户 A 和 B,用户 A 向用户 B 发送消息,当用户 B 收到该消息并检查该消息是否存在时,Firebase 会返回 true。然后用户B关闭应用程序,用户A删除数据库上的消息,用户B重新启动应用程序并再次检查,但即使用户A删除了消息,它仍然返回true

P/s : 我正在使用持久模式

这是数据库结构

----Messages
    |---UserA
    |------UserB
    |---------MessageId
    |---UserB
    |------UserA
    |---------MessageId  

检查代码是否存在(在用户 B 设备上运行)

             ROOT_REF.child("Messages").child("UserA").child(userB_Id).orderByKey().equalTo(messageId)
.addListenerForSingleValueEvent(new ValueEventListener() {
            @Override
            public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
                if (dataSnapshot.exists()){
                    //do stuff
                }else {

                }
            }

            @Override
            public void onCancelled(@NonNull DatabaseError databaseError) {

            }
        });


更新

我把代码改成

ROOT_REF.child("Messages").child("UserA").child(userB_Id).child(messageId)
.addListenerForSingleValueEvent(new ValueEventListener() {});


但即使我从数据库中删除它仍然有数据

更新 2

也试过这段代码,但它仍然返回数据并且快照仍然存在

ROOT_REF.child("Messages").child("UserA").child(userB_Id).child(messageId).keepSynced(true);

ROOT_REF.child("Messages").child("UserA").child(userB_Id).child(messageId)
.addListenerForSingleValueEvent(new ValueEventListener() {

//after do stuff 

ROOT_REF.child("Messages").child("UserA").child(userB_Id).child(messageId).keepSynced(false);

});

现在我仍然卡住了,但我使用的是双倍查询的临时解决方案,第一个查询将无法使用,我们将从第二个查询中获取数据

ROOT_REF.child("Messages").child("UserA").child(userB_Id).child(messageId)
.addListenerForSingleValueEvent(new ValueEventListener() {

// dont use the first one

 ROOT_REF.child("Messages").child("UserA").child(userB_Id).child(messageId)
.addListenerForSingleValueEvent(new ValueEventListener() {
//get data from the second one
});

});

最终更新: 如果我想在我的应用程序中使用该数据库结构检查其他节点上的数据,这可能是不可能的。要做到这一点,我需要在Messsages节点上附加keepsynced或添加一个监听器并缓存最后的数据,这对于几乎应用程序来说根本不方便。

【问题讨论】:

  • 注意.orderByKey().equalTo(messageId).child(messageId)相同,只是返回数据的格式不同。
  • 除此之外:addListenerForSingleValueEvent 和磁盘持久性不能很好地协同工作。使用addListenerForSingleValueEvent 将立即从缓存中返回值。见stackoverflow.com/a/34487195
  • 我在当前用户数据库节点上使用了KeepSynced,而不是在其他用户节点上。如何检查其他用户节点上是否存在子节点

标签: android firebase-realtime-database


【解决方案1】:

确保当用户 A 从服务器删除 messageId 消息时,该消息的两个用户副本(Messages/UserA/UserB/messageIdMessages/UserB/UserA/messageId)都被删除。

在您的问题代码中,您执行的是查询,而不是简单的数据库查找。当您使用任何orderBy 函数时,您总是会得到一个“存在”的快照对象,但您必须查看返回的快照的子对象,因为这是存储查询结果的地方。

Documentation on working with lists

总结,通过查询的结果,

在您的情况下,可以通过不在此行上使用 orderByKey() 来避免(和优化)这个问题:

ROOT_REF.child("Messages").child("UserA").child(userB_Id).orderByKey().equalTo(messageId).addListenerForSingleValueEvent(new ValueEventListener() {

并将其简化为基本的数据库查找,snapshot.exists() 将按照您在问题中的预期工作:

ROOT_REF.child("Messages").child("UserA").child(userB_Id).child(messageId).addListenerForSingleValueEvent(new ValueEventListener() {

【讨论】:

  • 请看我的更新
猜你喜欢
  • 2016-05-21
  • 2020-10-27
  • 2018-12-31
  • 2013-10-11
  • 1970-01-01
  • 1970-01-01
  • 2017-10-15
  • 1970-01-01
  • 2020-06-06
相关资源
最近更新 更多