如何解决Flutter/Dart中RangeError (index): Valid value range is empty: 1错误
错误原因
- 未处理FutureBuilder的异步加载状态:FutureBuilder加载assets文件是异步操作,在snapshot还未返回数据时,
snapshot.data为null,此时用CsvToListConverter转换得到的csvTable是空数组,直接访问索引就会触发范围错误。 - 索引计算逻辑存在潜在越界风险:你设置了TransformerPageView的
loop: true开启循环滚动,当csvTable长度异常(比如解析到空行、文件读取失败)时,也会触发索引越界。 - 若pubspec.yaml中未正确配置
assets/questions.csv的路径,会导致rootBundle加载文件失败,snapshot.data为空同样会触发该报错。
解决方法
按以下步骤修改即可:
- 给FutureBuilder增加加载状态判断,只有当snapshot有数据时再渲染页面内容,加载过程中显示加载指示器。
- 解析完CSV后直接删除表头行,后续直接用index访问数据,不需要额外加1,降低索引计算出错概率。
- 增加索引有效性校验,避免极端情况的越界问题。
- 确认pubspec.yaml中已经添加了assets的配置,示例配置如下:
flutter: assets: - assets/questions.csv
修改后的完整代码:
class _CsvState extends State<Csv> { @override Widget build(BuildContext context) { return FutureBuilder<String>( future: rootBundle.loadString('assets/questions.csv'), builder: (BuildContext context, AsyncSnapshot<String> snapshot) { // 处理加载中状态 if (!snapshot.hasData) { return Scaffold( appBar: AppBar(title: const Text("A1 German Vocabulary")), body: const Center(child: CircularProgressIndicator()), ); } List<List<dynamic>> csvTable = const CsvToListConverter().convert(snapshot.data); // 移除表头行 if (csvTable.isNotEmpty) csvTable.removeAt(0); // 处理无数据的情况 if (csvTable.isEmpty) { return Scaffold( appBar: AppBar(title: const Text("A1 German Vocabulary")), body: const Center(child: Text("暂无数据")), ); } return Scaffold( appBar: AppBar(title: const Text("A1 German Vocabulary")), body: TransformerPageView( itemCount: csvTable.length, loop: true, viewportFraction: 0.8, itemBuilder: (BuildContext context, int index1) { // 额外索引校验,避免越界 if (index1 >= csvTable.length || csvTable[index1].length < 4) { return const SizedBox.shrink(); } return Padding( padding: const EdgeInsets.all(10.0), child: Material( elevation: 8.0, textStyle: const TextStyle(color: Colors.white), borderRadius: BorderRadius.circular(10.0), child: Stack( fit: StackFit.expand, children: <Widget>[ Positioned( left: 10.0, right: 10.0, top: 100.0, child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: <Widget>[ Container( alignment: Alignment.center, child: Text( csvTable[index1][0], style: const TextStyle( fontSize: 24.0, color: Colors.black, ), ), ), const SizedBox(height: 20,), Container( alignment: Alignment.center, child: Text( csvTable[index1][1], textAlign: TextAlign.center, style: const TextStyle( fontSize: 24.0, color: Colors.black, ), ), ), const SizedBox(height: 20,), Container( margin: const EdgeInsets.only(left: 10.0, right: 20.0), child: const Divider( color: Colors.black, height: 36, ), ), Container( alignment: Alignment.center, child: Text( csvTable[index1][2], style: const TextStyle( fontSize: 24.0, color: Colors.black, height: 2 ), ), ), const SizedBox(height: 20,), Container( alignment: Alignment.center, child: Text( csvTable[index1][3], textAlign: TextAlign.center, style: const TextStyle( fontSize: 24.0, color: Colors.black, ), ), ), ], ), ) ], ), ), ); }, ), ); } ); } }
内容的提问来源于stack exchange,提问作者u2k
相关产品推荐
相关产品推荐

