Flutter获取Firebase两个集合数据时触发RangeError索引越界报错

报错原因
抛出RangeError (index): Invalid value: Valid value range is empty: 0的直接原因是未做非空判断就直接访问空数组的下标0:
你对Employee和Users两个集合执行条件查询后,没有校验查询返回的文档数组是否有内容,就直接写snap.docs[0]、snap2.docs[0]取第一条数据。如果输入的id在Employee集合中不存在,snap.docs就是长度为0的空数组,访问下标0就会触发越界错误;同理id不在Users集合时,访问snap2.docs[0]也会报同样的错。
原代码还存在两个明显问题:
- 两个查询是串行执行的,必须等第一个查询返回才会发起第二个,不必要地增加了等待时间
- 没有覆盖"账号不存在"、"密码不匹配"的异常场景,运行时会出现无响应、未捕获异常等问题
修改方案
- 访问查询结果前先判断文档数组是否为空,禁止直接取下标
0,从根源避免索引越界错误 - 将两个串行的集合查询改为并行执行,减少接口等待时长
- 补全"账号不存在"、"密码错误"的异常分支处理,避免逻辑遗漏
修改后的可运行代码如下:
// 并行发起两个集合的查询,缩短总等待时间 final results = await Future.wait([ FirebaseFirestore.instance.collection("Employee").where('id', isEqualTo: id).get(), FirebaseFirestore.instance.collection("Users").where('uid', isEqualTo: id).get() ]); QuerySnapshot employeeSnap = results[0]; QuerySnapshot userSnap = results[1]; // 提前判断查询结果是否存在,避免索引越界 bool isEmployeeExist = employeeSnap.docs.isNotEmpty; bool isUserExist = userSnap.docs.isNotEmpty; // 两个集合都未查询到对应账号 if (!isEmployeeExist && !isUserExist) { // 替换为你的业务提示逻辑,例如弹出提示"账号不存在,请检查输入" print("账号不存在"); return; } sharedPreferences = await SharedPreferences.getInstance(); User.employeeId = id; // 员工账号密码校验通过 if (isEmployeeExist && password == employeeSnap.docs[0]['password']) { await sharedPreferences.setString('employeeId', id); navigateNext(HomeScreen()); return; } // 管理员账号密码校验通过 if (isUserExist && password == userSnap.docs[0]['upassword']) { await sharedPreferences.setString('userId', id); navigateNext(AdminScreen()); return; } // 走到此处说明账号存在但密码输入错误 // 替换为你的业务提示逻辑,例如弹出提示"密码错误,请重新输入" print("密码错误");
安全提示:明文在数据库中存储密码存在极大的泄露风险,正式环境建议对接Firebase Auth完成官方的身份校验流程,不要自行在Firestore中存储明文密码。
内容的提问来源于stack exchange,提问作者mahmoud kotb
相关产品推荐
相关产品推荐

