动态更改Android上Firebase查询引用的限制

mar*_*rei 9 java android firebase

我在我的Android应用程序中使用Firebase作为聊天功能.我的目标是支持:

  1. 每当新消息到达或现有消息发生变化或被删除时,都会进行实时更新
  2. 无限向后滚动消息历史.

第一部分似乎很容易.我创建了一个带限制的firebase引用.

ref = new Firebase(FIREBASE_URL).child("chat").limitToFirst(50);
Run Code Online (Sandbox Code Playgroud)

然后,该引用由添加侦听器的适配器使用.然后在数据发生变化时修改List.

ref.addChildEventListener(new ChildEventListener() {
    @Override
    public void onChildAdded(DataSnapshot dataSnapshot, String previousChildName) {...}
    @Override
    public void onChildChanged(DataSnapshot dataSnapshot, String s) {...}
    @Override
    public void onChildRemoved(DataSnapshot dataSnapshot) {...}
    ...
Run Code Online (Sandbox Code Playgroud)

第二部分是我努力寻找正确方法的地方.当用户到达列表的末尾时,我想加载较旧的消息并将它们添加到消息列表中(无限滚动).

首选的解决方案是简单地调用类似ref.changeLimitToFirst(100)但不存在这样的方法.

用firebase解决这个问题的最佳方法是什么?


编辑:

我删除了我最初建议的解决方案,因为它们没有帮助澄清问题.相反,我将列出自我最初提出问题以来我发现的新解决方案.

如果您知道更好,更优雅的方法,请留下答案!

  1. 最简单的方法似乎是从旧的Query中删除侦听器; 然后使用新限制创建一个新查询.可以在Firebase-UI-Android lib的拉取请求中找到此方法的示例.缺点是:
    • 添加新侦听器后,您将收到每个子节点的child_added事件,而不仅仅是您尝试加载的事件.因此,在添加子列表之前,您必须检查子列表中是否已存在子项.这意味着如果列表变长,将会有很多次迭代.
    • 您不知道何时完成加载.解决方法是添加一个额外的值侦听器,一旦加载完整的快照,就会触发该值(从而完成新页面的加载).
  2. 第二种方法是通过监听value事件来单独加载每个页面.不幸的是,offset()之类的东西不存在.所以要走的路是记住你加载的最后一个项目并将其传递给startAt方法.缺点:
    • 为了接收更新,您需要删除旧的子侦听器,并在每次加载新页面时添加新的子侦听器(因为限制更改).然后,此侦听器将接收您必须过滤掉的child_added事件(请参见上文).
    • 加载第一页的时间与加载时间和添加第二页之间的最后一项的位置可能会发生变化.如果您的数据顺序可能会发生变化,则无法确定您保存的子项是否仍是下一个查询的正确参考.在这种情况下,您需要再次使用子侦听器来接收先前加载的数据的更新.

Jay*_*Jay 3

在 Firebase 中,有两种检索数据的方法:

1)通过EVENT观察节点

2)在节点内查询特定数据

这两个项目是独立的功能,但行为方式相似,并且都可以从 Firebase 检索数据。

通过 Firebase 查询,您可以根据各种因素有选择地检索数据。

问题的答案取决于数据的结构。假设这个结构

Msgs
  node_ref:
    index: 0
    msg: 'Hows the weather'
  node_ref:
    index: 1
    msg: 'Hot'
Run Code Online (Sandbox Code Playgroud)

回答:1) 实时更新

如果 Msgs 节点具有侦听器,则应用程序会收到该节点的任何更改的通知,并且可用于加载该节点内数据的初始快照,然后侦听该节点内消息的添加、更新和删除。

根据您的更新,您有办法加载前 50 个。但是,第 2 部分的答案可能是另一个解决方案。

回答:2)向后滚动(或向前滚动,或加载数据集)

添加侦听器与在 Msgs 节点上针对特定消息执行 Firebase 查询无关。查询将用于加载子索引为 1 的消息,或子索引小于 10 的任何消息,或包含子索引范围从 5 开始到 10 结束的消息。

这可以通过范围查询来完成:使用 startAt()、endAt() 和 equalTo() 允许您选择查询的任意起点和终点。

因此,如果 Msgs 节点包含 100 条消息,并且显示子索引为 90-99 的消息,并且用户向后滚动(到较旧的消息),则可以执行简单的范围查询来查询消息 80-89,然后将加载并显示。类似地,如果显示消息 0-9(最旧的)并且用户向前滚动,则从消息 10-19 进行范围查询。

正如您所看到的,利用查询加载数据时根本不需要侦听器。侦听器将用于告诉应用程序何时有数据(添加、更新或删除)

话虽这么说,有一些方法可以在不查询的情况下执行此操作,但这取决于数据的结构以及您希望 UI 的行为方式。