向FireStore写入数据无网络失败时如何显示错误提示SnackBar
问题原因
Firebase Firestore 默认开启了离线持久化能力,当设备处于离线状态时,你调用add方法执行的写入操作不会立即抛出异常,也不会立刻执行完成:Firestore 会将本次写入操作暂存到本地缓存,等待网络恢复后自动同步到云端,因此你代码中await的Future既不会触发成功回调,也不会抛出异常进入catch块,自然两个SnackBar都不会弹出。
解决方案
你可以根据业务需求选择以下两种方案:
方案1:提交前先检查设备网络状态
如果你的业务逻辑要求必须在线才能提交数据,可以在调用Firestore写入前先检查当前网络状态,无网络时直接抛出错误提示。
- 先添加
connectivity_plus依赖到pubspec.yaml - 调整代码如下:
Future<void> validateForm() async { try { // 先检查网络连接状态 var connectivityResult = await Connectivity().checkConnectivity(); if (connectivityResult == ConnectivityResult.none) { throw "当前设备无网络连接,无法提交数据"; } await FirebaseFirestore.instance.collection('collectionPath').add({ 'full_name': 'John Doe', 'company': 'Stokes and Sons', 'age': '42', }); ScaffoldMessenger.of(context).showSnackBar(successSnackBar); } catch (e) { print(e.toString()); ScaffoldMessenger.of(context).showSnackBar(errorSnackBar); } }
注意:
connectivity_plus仅能检测设备是否连接到网络,无法判断网络是否可正常访问外网,若需要更严格的校验,可以额外加一个网络连通性测试。
方案2:强制等待服务端确认写入成功再返回
如果需要确认数据已经真正同步到云端才判定为提交成功,可以修改写入逻辑,要求必须获得服务端响应才算完成,此时离线状态下写入会直接抛出异常:
Future<void> validateForm() async { try { final docRef = FirebaseFirestore.instance.collection('collectionPath').doc(); // 先写入本地 await docRef.set({ 'full_name': 'John Doe', 'company': 'Stokes and Sons', 'age': '42', }); // 强制从服务端获取数据,确认写入成功 await docRef.get(const GetOptions(source: Source.server)); ScaffoldMessenger.of(context).showSnackBar(successSnackBar); } catch (e) { print(e.toString()); ScaffoldMessenger.of(context).showSnackBar(errorSnackBar); } }
注意:该方案会失去Firestore离线持久化的优势,提交操作必须等待网络交互完成,适合对数据一致性要求极高的场景。
内容的提问来源于stack exchange,提问作者Sunshine
相关产品推荐
相关产品推荐

