如何知道何时使用实时Firebase数据库中的侦听器从根节点提取所有初始数据



目标:

我的目标是获取初始数据,在我确定所有数据都已获取后更新UI,并立即继续观察变化:

问题

我看到了两种方法:

  1. 使用getData方法并一次获取所有数据(庞大)。这是可以的,因为我知道我已经一次获取了所有数据,并且我可以相应地更新UI并继续侦听更改(CRUD)

这种方法的问题是,我不能只在之后附加侦听器,以侦听新添加(插入),然后等待新项目。它的工作方式不同(这是有道理的,因为我在没有通过侦听器与数据库同步的情况下获取数据),并且在我附加侦听器后,我会立即触发它的回调,触发次数与根节点中当前项目的数量一样多。所以我得到的数据很可能是一样的。

所以这似乎有些过头了。

  1. 实现这一点的第二种方法是附加侦听器,并获取所有数据。但问题是,我不知道所有数据是什么时候提取的,因为它是按顺序来的,一项接一项。因此,我无法相应地更新UI

以下是一些代码示例:

我目前正在使用getData方法获取所有以前的数据,如下所示:

func getInitialData(completion: @escaping DataReadCompletionHandler){

rootNodeReference.getData { optionalError, snapshot in
if let error = optionalError {
completion([])
return
}
if let value = snapshot.value,
let models = self.parseData(type: [MyModel].self, data: value) as? [MyModel]{

completion([MyModel](models.values))
}
}
}

正如我所说,有了这个,我确信我已经拥有了以前的所有数据,我可以相应地设置我的UI。

在此之后,我只对新的更新(更新、删除、插入)感兴趣

后来我通过听众联系。以下是一个侦听器的示例,它在向根节点添加新内容时进行侦听:

rootNodeReference.observe(DataEventType.childAdded, with: {[weak self] snapshot in
guard let `self` = self else {return}

if let value = snapshot.value,
let model = self.parseData(type: MyModel.self, data: value) as? MyModel{
self.firebaseReadDelegate?.event(type: .childAdded, model: model)
}
}) 

如果有了这个监听器,我可以在添加新内容时继续更新,那就太好了。

不过,我猜是选项2。这将是一个更好的方法,但如何知道我什么时候通过听众获得了所有数据?

有两种方法可以做到这一点,但它们都依赖于Firebase对事件触发顺序的相同保证。

当在同一路径/查询中同时观察到child事件和value事件时,value事件会在所有相应的child事件之后触发

因为如果这能保证,你可以在.value中添加一个额外的监听器

rootNodeReference.observeSingleEvent(of: DataEventType.value, with: { snapshot in
... the initial data is all loaded
})

添加第二个侦听器不会增加从数据库中读取的数据量,因为Firebase会在场景后面对它们进行重复数据消除。


您也可以放弃childAdded侦听器,只使用单个observe(.value,如通过观察值事件读取列表的文档所示:

rootNodeReference.observe(.value) { snapshot in
for child in snapshot.children {
...
}
}

最新更新