Flutter删除录音文件时触发RangeError(index)下标越界错误如何解决

报错信息如下:
'RangeError (index): Invalid value: Not in inclusive range 0..14: 15'
问题根本原因
- 你在弹窗组件
DialogBuilder中直接修改父组件传递的文件列表引用,删除元素后,弹窗仍然持有旧的索引值,子组件的setState操作或音频播放的状态回调后续尝试访问该索引时,对应位置的元素已经被移除,就会触发越界 - 删除操作执行后没有先关闭弹窗,弹窗存活期间的任何状态更新都会触发越界访问风险
- 直接在子组件修改父组件的状态不符合Flutter单向数据流规范,父组件无法精准感知状态变化时机,容易出现异步时序问题
- 进度条的数值没有做边界校验,当播放时长异常时也可能触发数值越界报错
具体修复步骤
步骤1:给弹窗组件新增删除回调,不要在子组件直接修改父组件状态
修改DialogBuilder的定义,新增删除回调参数,将删除事件交给父组件处理:
class DialogBuilder extends StatefulWidget { final String path; final int index; final List file; // 新增删除回调 final Function(int deleteIndex) onDelete; DialogBuilder({ required this.path, required this.index, required this.file, required this.onDelete, // 加入构造参数 }); @override _DialogBuilderState createState() => _DialogBuilderState(); }
步骤2:重写删除方法,先关闭弹窗再执行操作,增加合法性判断
修改_delete方法,先判断索引合法性、关闭弹窗,再执行文件删除和回调通知,删除原有的子组件setState操作,状态更新统一交给父组件处理:
_delete() async { // 先判断索引是否合法,不合法直接关闭弹窗 if (widget.index < 0 || widget.index >= widget.file.length) { Navigator.pop(context); return; } // 先关闭弹窗,避免后续操作触发子组件状态更新导致越界 Navigator.pop(context); try { // 等待异步删除操作执行完成 await widget.file[widget.index].delete(recursive: true); // 调用回调通知父组件删除对应索引的元素 widget.onDelete(widget.index); } catch (e) { // 可在这里添加删除失败的提示逻辑,比如弹出Toast debugPrint('删除文件失败:$e'); } }
步骤3:父组件实现删除回调,自行更新状态
在父组件_AudioViewerState中实现删除逻辑,收到回调后调用setState刷新列表:
// 加入父组件的_AudioViewerState类中 void _onDeleteItem(int index) { setState(() { file.removeAt(index); }); }
将该回调通过AudioViewerCustomTile层层传递给DialogBuilder组件即可。
步骤4:修复进度条数值越界问题
给LinearProgressIndicator的value增加边界校验,避免出现数值超出0-1范围的报错:
LinearProgressIndicator( backgroundColor: Colors.grey[300], valueColor: AlwaysStoppedAnimation(Colors.deepOrangeAccent), value: duration.inMilliseconds > 0 ? (position.inMilliseconds / duration.inMilliseconds).clamp(0.0, 1.0) : 0.0, ),
完成以上修改后,索引越界的问题就可以完全解决。
内容的提问来源于stack exchange,提问作者jiji
相关产品推荐
相关产品推荐

