Firebase onChildAdded 用于新数据的添加。

7
如果我的firebase引用中存储了50000个项目列表,并且自上次客户端在线并监听以来已添加了5个项目,则我必须使用哪个回调函数,使其仅对已添加的5个新项目触发?
我在客户端启用了离线持久性Firebase.getDefaultConfig().setPersistenceEnabled(true);。我有一个绑定到活动的监听器,用于监听引用中添加的子项。每次创建活动时,onChildAdded都会被调用以获取引用中的所有数据。是否可以使onChildAddedonChildRemoved仅针对本地缓存和firebase服务器上的数据之间的“差异”而被调用?如果不可能,那么是否只能在最近一次firebase更新后触发这些onChild*回调函数?

你是否已经尝试使用update()的onComplete回调函数? - not_a_bot
从Android文档中看来,updateChildren()类似于setValue()。我不知道如何使用它来弄清楚我要做什么。我已经在问题中添加了一个示例,这可能会使我试图实现的内容更清晰。 - Vinay Nagaraj
2个回答

13
每次创建活动时,都会调用onChildAdded来处理引用中所有数据。是否可能使onChildAdded和onChildRemoved仅针对本地缓存和Firebase服务器上的数据之间的“差异”而被调用?
不,这是不可能的。根据事件类型文档
child_added会为每个现有子项触发一次,然后每当在指定路径添加新子项时再次触发。
现在回到您最初的问题:
使用哪个回调函数,才能仅对已添加的5个新项进行触发?
那将是:
ref.limitToLast(5)...

但这需要您知道自上次监听以来添加到列表中的项目数量。
更常见的解决方案是跟踪您已经看到的最后一项,然后使用 startAt() 从上次位置开始触发事件:
ref.orderByKey().startAt("-Ksakjhds32139")...

你可以在共享偏好设置中保留最后一个键。
同样,你可以使用以下代码来保存活动上次可见的时间:
long lastActive = new Date().getTime();

然后在每个项目中添加一个timestamp,并使用Firebase.ServerValue.TIMESTAMP,然后:

ref.orderByChild("timetstamp").startAt(lastActive+1)...

这个解决方案是否也会触发childChanged和childRemoved事件? - Vinay Nagaraj
是的,自上次查询以来的事件FIFO将是最佳选择,但看起来我将使用一个childEventListener。在捕获事件时,我将通过本地存储已经看到的数据来忽略它。 - Vinay Nagaraj
我不确定是怎么回事,但 onChildRemoved 似乎能够正确触发。我在我的安卓手机上杀掉了所有进程(应用程序不再监听 Firebase),使用我的 Firebase 应用仪表板从列表中删除一个项目,然后启动我的手机上的应用程序并导航到相关活动。我删除的项目会在消失之前出现一秒钟。目前我对这种行为感到满意,因为数据很少从这个特定的列表中删除,RC 和 U 是主要的用例。不过我想我应该编写一些广泛的测试来真正理解发生了什么。 - Vinay Nagaraj
是的,我进行了多次编辑,多次添加和删除相同的数据,并调用了 onChildChanged 方法。谢谢! - Vinay Nagaraj
1
我喜欢你上次的解决方案,但服务器和本地设备之间的时间差怎么办? - sivi
显示剩余4条评论

1
你应该使用on('child_changed')。通常,on()用于监听特定位置的数据更改。但是,on('child_changed')会通知你当一个子节点(或其任何后代)中存储的数据发生更改时。它将向回调传递一个包含新子内容的数据快照。请记住,单个child_changed事件可能代表对子节点的多个更改。

2
在这种情况下,他不会得到他要求的5个项目,而是会得到所有50000多个项目的列表(请参见问题的最后一段)。 - seanpj
1
你说得对,他也可以使用 limitToLast(x) 来获取最后 X 个更新的子节点。 - not_a_bot

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接