当使用get()
方法从Firestore
中获取所有文档时,默认情况下,如果没有互联网连接,它不会抛出异常。相反,它会查找该高速缓存并返回缓存的数据。但有时候你需要知道一个集合当前是否为空或者你只是无法连接到数据库。
对于获取数据,有一个解决方案:可以将GetOptions
参数设置为Source.server
。这样,如果无法访问服务器,则会引发错误。
现在,我正在为snapshots()
方法寻找一个与此选项等效的选项,它返回一个Stream
,而不仅仅是单个数据。
因此:
await _firestore
.collection('stuff')
.where("someBool", isEqualTo: false)
.get(const GetOptions(source: Source.server));
将在错误连接上引发FirebaseException
,而:
_firestore
.collection('stuff')
.where("someBool", isEqualTo: false)
.snapshots()
.listen((snap) { ... }, onError: (e) {
//never called...
debugPrint(e.toString());
});
在这个例子中我就是找不到答案。
我得到的最接近的解决方案是检查snap.metadata.isFromCache
并在值为true
时抛出异常。但这并不可靠。False意味着快照保证与服务器保持最新。但在某些情况下,即使它从服务器得到了有效的响应,它也是true
。
编辑:如果我在本地而不是直接在查询中过滤someBool
,isFromCache
属性将是一个解决方案。
_firestore
.collection('stuff')
.where("someBool", isEqualTo: false)
.snapshots(includeMetadataChanges: true)
.listen((snap) {
//`hasPendingWrites` is false in all these cases:
// 1. changing a document's `someBool` field from `false` to `true` and vise versa
// 2. requesting with server connection
// 3. requesting without server connection
debugPrint("snap metadata pendingWrites is: ${snap.metadata.hasPendingWrites}");
if (snap.metadata.isFromCache) {
//I thought data from cache is only used when there's trouble connecting to the server which is not the case:
//
//no internet connection will indeed cause this value to be true
//but changing a document's `someBool` field from `false` to `true` however, will cause it to be true, too
debugPrint("metadata of this snap is from cache -> throwing NoInternetException");
throw NoInternetException();
}
}, onError: (e) {
//never called...
debugPrint(e.toString());
});
编辑:我已禁用脱机持久性:
db.settings = const Settings(persistenceEnabled: false);
实验:更新文档的someBool
域(直接从Firestore Console
):
- 使用互联网:*
对错:14n1x是15n1x,16n1x是17n1x
假到真:pendingWrites
是false
,isFromCache
是true
在收听Stream
时关闭互联网:
第一个是第一个
因此,互联网的“假对真”情况导致使用isFromCache
成员的误报。
编辑:
该文件规定:
如果调用[DocumentReference.snapshots]或[Query.snapshots]时将includeMetadataChanges
参数设置为true
,则一旦客户端从后端接收到最新数据,就会收到另一个isFomCache
等于false
的快照。
现在,在此误报情况下(将bool从false
设置为true
),Stream
触发两次:
- 首次使用
isFromCache
:x1米36英寸1x - 第二次(第一次后立即):
isFromCache
:x1米38英寸
因此,由于某种原因,即使有到服务器的连接,Firestore也会该高速缓存中读取。
4条答案
按热度按时间zf9nrax11#
即使您的应用暂时失去网络连接,Firebase应用也能正常工作。此外,Firebase提供了用于在本地持久化数据、管理在线状态和处理延迟的工具。
例如,您可以检查Internet连接,如检测连接状态
有关更多详细信息,您可以查看以下链接:-https://firebase.google.com/docs/database/flutter/offline-capabilities
特别是消防仓库,你可以遵循这个
有关更多详细信息,请访问以下链接(用于Firestore):-https://firebase.google.com/docs/firestore/manage-data/enable-offline#dart_2
bvjveswy2#
为了做你想做的事,你必须:首先确保已禁用并清除缓存:
现在,当你尝试在没有网络连接的情况下访问任何东西时,你应该得到一个“isFromCache”等于true的空快照。不幸的是,在这种情况下没有错误。这只是它的设计方式。
希望我能帮上忙。
vu8f3i0k3#
您所描述的行为正是Firestore开发人员所希望的,而且它确实有其缺点。
我唯一要添加到您当前解决方案中的是使用connectivity_plus或internet_connection_checker之类的方法进行连接检查
connectivity_plus只会检测设备是否开启了Wifi/4G,但它非常轻,不会影响电池。
internet_connection_checker将为您提供有关连接的“真实的”信息,但它必须查询服务器才能获得此信息。
它会100%正常工作吗?可能不会。
在一些用例中,即使有这种“安全性”,您也可能得到误报(甚至是假阴性,这是最糟糕的)。
agyaoht74#
看到我的票我在六月打开:https://github.com/firebase/flutterfire/issues/8961
正如您在最后一个条目中看到的,我在Firebase支持处打开了一个功能请求,要求在Query.snapshots和DocReference.snaphots调用中添加GetOptions参数。
此外,您还可以查看Nimbostratus包,它试图克服Firestore中的当前限制。