我正在研究一个使用Firebase RTDB的Flutter应用程序。我对keepSynced()
的机制有点不清楚:
我们的应用程序创建新的集合并向这些集合添加数据。该应用程序还观察这些集合以显示数据。在此过程中,我们调用keepSynced(true)
以保持这些查询的离线缓存活动。现在我们注意到,当创建一个新的集合+在离线时调用keepSynced(true)
时,我们在新集合上注册的侦听器直到应用程序再次上线才接收数据。从那时起,缓存和更新侦听器按预期工作(在线+离线)。
// Execute this while offline:
// Enable permanent offline sync for a new node that doesn't exist yet on the Firebase server
await database.ref().child('new_node').keepSynced(true);
// Register listener
database.ref().child('new_node').onValue.listen((event) => print(event));
// Add data
database.ref().child('new_node/child').set({'key': 'value'});
设备上线后,监听器才会触发。
关于keepSynced()
状态的文档
通过在一个位置上调用keepSynced(true),该位置的数据将自动下载并保持同步,即使没有为该位置附加侦听器。此外,当一个位置保持同步时,它不会从持久磁盘缓存中被删除。
所以它实际上需要与Firebase后端连接("将自动下载"),而调用keepSynced()
为了离线缓存/查询工作?
您可以在任何时候调用keepSynced
,但是客户端只有在连接到服务器时才能从服务器下载数据。
如果这不是你观察到的行为,请编辑你的问题,包括一个最小的重现。
更新基于你问题中的新版本:
你看到的行为是不幸的,但在意料之中。
Firebase API保证(这些天没有记录)它永远不会向你的应用程序显示部分节点。因为你只设置了/new_node/child
,它不知道/new_node
的当前状态,它不会在new_node
上引发value
事件,因为它只有关于该节点的部分信息。
如果您在new_node
上监听child_added
, SDK将在这种情况下引发一个事件——但它不会引发一个值事件,因为它直到可以确定它有new_node
的完整快照。
最常见的两个路径是:
- 在JSON树的较低级别侦听,例如侦听
child_*
事件(如上所述)。 - 在所有
new_node
上执行初始写操作,以便本地SDK知道节点的预期初始状态是什么,然后可以执行低级写操作。如果存在无法擦除的数据,则可以使用安全规则拒绝服务器上的这个启动写操作。