You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

enter image description here

报错原因

抛出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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 20:09:10