ChildEventListener 不一致?

ChildEventListener inconsistency?

我一直在使用 Firebase Android Api 并发现了这个功能(在我看来是不一致的)。我想征求意见 and/or 解决它在我的场景中引起的问题。

在Android应用程序中,我建立了一个标准'ChildEventListener',形式如下:

new Firebase("https://[MYTEST].firebaseio.com/").addChildEventListener(
  new ChildEventListener() {
    @Override
    public void onChildAdded(DataSnapshot data, String prev) {
      Log.i("_", "add " + data);
    }
    @Override
    public void onChildChanged(DataSnapshot data, String prev) {
      Log.i("_", "chg " + data);
    }
    @Override
    public void onChildRemoved(DataSnapshot data) {
      Log.i("_", "del " + data);
    }
    @Override
    public void onChildMoved(DataSnapshot data, String prev) {
      Log.i("_", "mov " + data);
    }
    @Override
    public void onCancelled(FirebaseError err) {
      Log.i("_", "err " + err.getMessage());
    }
  }
);

工作起来很有魅力,捕获我可以从 Firebase 仪表板中抛出的所有事件。

下一个:

我知道此行为可能是设计使然,但即使我保留本地节点列表和简单差异可能会给我一组已删除的节点,它也会带来问题。但事实是,一个空的节点列表不会生成 'onChildAdded()' 事件,因此很难放置计算已删除节点的代码。

我想还有另一种方法可以解决这个“死时删除”的问题,请向我指出正确的方向。

总结:Firebase 数据库同步状态。与消息传递机制不同,它不同步状态更改。

当您启动一个没有缓存 Firebase 数据库数据的应用程序时,Firebase API 会同步您的应用程序与存储信息同步所需的最少数据。因此,对于当时服务器上存在的任何数据,您都会得到一个 child_added 事件。

如果您的应用程序在连接时已经从数据库中获取了以前的信息(例如,当您使用 Firebase 的磁盘持久性时,或者当您的连接在没有重新启动应用程序的情况下恢复时),API 将触发使数据的本地版本与服务器保持同步所必需的事件。所以在这种情况下,您可能会看到 child_addedchild_changedchild_movedchild_removed 事件。

无法保证在您的客户端未连接时传输状态更改。

实践中的状态同步

这方面的一个例子:

  • 上网
  • 获取所有数据
  • 下线
  • 另一个用户添加值 A
  • 另一个用户删除了值 A
  • 重新上线

您的应用现在不会收到任何表明值 A 曾经存在的指示。这就是状态同步的工作方式。

存储状态变化,而不是状态

如果您的应用要求每个客户端都知道每个状态更改,您应该将实际状态 更改 存储在数据库中。

  • 上网
  • 获取所有数据
  • 下线
  • 另一个用户写记录"add value A"
  • 另一个用户写记录"remove value A"
  • 重新上线

客户端现在将接收所有状态更改,因为您将这些更改存储在数据库中。

通常,您还需要 运行 一个可信进程,将所有状态更改记录再次聚合到一个 "current state" 中,以便更快地访问。