Flutter Firebase空数据场景下异步重复名校验状态处理
问题原因
你的代码点击无响应是两个逻辑错误导致的:
- 你用
await for监听snapshots()返回的实时数据流,当新用户的borrowers集合为空时,第一次返回的快照里docs是空数组,内层遍历文档的for循环根本不会执行,函数没有触发任何return语句,会一直挂起等待流的后续数据,所以await永远等不到返回值,后续逻辑全卡住。 - 就算集合里有数据,你现在的遍历逻辑只要拿到第一个文档就直接return结果,不会检查剩下的文档:如果第一个文档的名称不匹配,哪怕后面的文档有重名,也会误判为不存在。
- 做单次存在性校验根本不需要用实时流监听,拉取一次数据判断就够,用流反而会导致逻辑挂起、资源浪费。
修复代码
1. 重写校验函数,用单次查询替代流监听
直接用字段匹配查询替代全量拉取遍历,性能更好,空集合场景也能正常返回结果:
// 明确声明返回值类型为Future<bool>,避免隐式返回null Future<bool> checkBorrowerAlreadyExists(String textfieldname) async { final queryResult = await _firestorem .collection('lender') .doc(auth.currentUser?.uid) .collection('borrowers') // 注意把'name'替换成你实际存储借款人名称的字段名 .where('name', isEqualTo: textfieldname) .limit(1) // 只需要查1条匹配结果,减少数据传输 .get(); // 查到匹配文档就返回true,否则返回false return queryResult.docs.isNotEmpty; }
如果你不想用where查询,非要手动遍历文档,记得遍历完所有文档之后再返回结果,空集合直接返回false:
Future<bool> checkBorrowerAlreadyExists(String textfieldname) async { final querySnapshot = await _firestorem .collection('lender') .doc(auth.currentUser?.uid) .collection('borrowers') .get(); // 空集合直接返回false if (querySnapshot.docs.isEmpty) return false; // 遍历所有文档检查是否存在匹配值 for (var doc in querySnapshot.docs) { if (doc.data().containsValue(textfieldname)) { return true; } } return false; }
2. 调整按钮点击回调逻辑
加个首尾空格过滤,避免用户输入无意义空格导致误判,空校验后直接中断后续逻辑:
onPressed: () async { final inputName = borrowerNameController.text.trim(); if (inputName.isEmpty) { Get.snackbar( 'Error:', "Borrower Name can't be empty", backgroundColor: Colors.red, ); return; } final nameExists = await checkBorrowerAlreadyExists(inputName); if (nameExists) { Get.snackbar( 'Error', 'Borrower Name already exists, Enter new name', backgroundColor: Colors.red, ); } else { // 在这里写Firebase数据上传逻辑即可 } }
内容的提问来源于stack exchange,提问作者Ganesh Sivakumar
相关产品推荐
相关产品推荐

