Flutter Firebase上传卡顿及子集合存储失败问题求助
一、先处理App Check配置错误
你遇到的Error getting App Check token; using placeholder token instead. Error: com.google.firebase.FirebaseException: No AppCheckProvider installed.错误,是因为Firebase App Check未完成初始化,导致请求验证失败,这很可能是子集合写入失效的核心原因。解决步骤:
确认依赖已添加
在pubspec.yaml中确保引入App Check依赖:dependencies: firebase_app_check: ^0.2.1+11 # 建议使用最新版本初始化App Check
在Firebase初始化完成后(通常放在main函数中)添加初始化代码:- 测试环境(Android):
await FirebaseAppCheck.instance.activate( androidProvider: AndroidProvider.debug, ); - 生产环境(Android):替换为
AndroidProvider.playIntegrity,并在Firebase控制台配置Play Integrity服务。 - iOS环境:测试用
IosProvider.debug,生产用IosProvider.deviceCheck。
- 测试环境(Android):
控制台配置补充
登录Firebase控制台的App Check页面,为你的应用启用对应验证提供者,测试环境需添加调试令牌。
二、排查子集合写入失效问题
除App Check的影响外,还需检查以下关键点:
1. 验证Firestore路径有效性
确认sharedPreferences!.getString("uid")和widget.model!.menuID是否返回有效值,可在saveInfo开头添加日志打印:
print("当前用户UID: ${sharedPreferences!.getString("uid")}"); print("目标菜单ID: ${widget.model!.menuID}");
若其中任一值为空,会导致路径无效,直接写入失败。
2. 检查Firestore安全规则
确保规则允许写入目标子集合和顶级items集合,示例规则如下:
rules_version = '2'; service cloud.firestore { match /databases/{database}/documents { match /sellers/{sellerId}/menus/{menuId}/items/{itemId} { allow write: if request.auth.uid == sellerId; } match /items/{itemId} { allow write: if request.auth.uid == resource.data.sellerUID; } } }
3. 添加错误捕获定位问题
你的代码未处理set方法的异常,需补充错误捕获来查看具体失败原因:
ref.set({/* 数据内容 */}) .catchError((error) { print("子集合写入失败原因: $error"); setState(() => uploading = false); // 此处可添加错误弹窗提示用户 }) .then((value) { itemsref.doc(uniqueIdName).set({/* 数据内容 */}) .catchError((error) { print("顶级items集合写入失败原因: $error"); }); });
4. 优化异步处理逻辑
validateUploadForm是异步函数,但调用saveInfo时未使用await,可能导致状态更新混乱。修改为:
// 在validateUploadForm中 await saveInfo(downloadUrl);
同时将saveInfo改为异步函数,用async/await替代then链,提升可读性和错误处理能力:
Future<void> saveInfo(String downloadUrl) async { try { final ref = FirebaseFirestore.instance .collection("sellers") .doc(sharedPreferences!.getString("uid")) .collection("menus") .doc(widget.model!.menuID) .collection("items") .doc(uniqueIdName); await ref.set({/* 子集合数据 */}); final itemsref = FirebaseFirestore.instance.collection("items"); await itemsref.doc(uniqueIdName).set({/* 顶级集合数据 */}); clearMenuUploadFrom(); setState(() { uniqueIdName = DateTime.now().millisecondsSinceEpoch.toString(); uploading = false; }); } catch (e) { print("保存操作总失败原因: $e"); setState(() => uploading = false); // 显示错误提示 } }
内容的提问来源于stack exchange,提问作者ghassen omri

