Flutter StreamBuilder报Infinity or NaN toInt错误如何解决
问题现象
构建StreamBuilder时抛出如下错误:
UnsupportedError: Unsupported operation: Infinity or NaN toInt
组件状态信息:组件为dirty状态,依赖项包括[_LocalizationsScope-[GlobalKey#7d7fa], _InheritedTheme],关联状态为_StreamBuilderBaseState<bool, AsyncSnapshot>#75e11
报错场景为:使用StreamBuilder监听加载状态,结合GridView.count实现日历类网格布局。
根因排查
这个错误的本质是组件渲染链路中出现了NaN(非数字)或Infinity(无穷大)的值,该值被传入需要整数类型的布局/绘制逻辑时触发类型转换失败,结合提供的代码,问题点集中在以下位置:
- 核心问题出在
Color.lerp的第三个插值参数计算逻辑:controller.countHabitsDone(day) / day.habits.length- 当
day.habits.length为0(即当天没有绑定任何习惯)时,除以0的运算会直接得到NaN值 - 若
countHabitsDone(day)返回值为null、或返回值远超day.habits.length,也会导致插值参数非法
- 当
Color.lerp拿到NaN的插值参数后,会计算出非法的颜色通道值,后续GridView布局、绘制阶段做整数转换时就会抛出该错误,错误栈会定位到上层的StreamBuilder构建节点,容易误导排查方向- 额外边界风险:代码中直接使用
snapshot.data!强制解包,若流发射异常值、初始值与实际流类型不匹配,也可能触发空值导致的非法运算
修复方案
针对上述问题点,逐处增加边界兜底逻辑即可:
- 做除法运算前先判断分母是否为0,避免除零产生NaN
- 对插值比例做范围限制,强制约束在
0.0~1.0的合法区间内 - 对快照数据、业务数据增加空值兜底,避免强制解包带来的风险
修正后的核心代码片段如下:
StreamBuilder<bool>( stream: controller.loading.stream, initialData: controller.loading.value, builder: (context, snapshot) { // 增加加载状态兜底,流未就绪时优先展示加载态 final isLoading = snapshot.data ?? true; return GridView.count( crossAxisCount: 7, mainAxisSpacing: 5, crossAxisSpacing: 5, shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), padding: const EdgeInsets.all(10), children: List.generate(days, (index) { if (index < whiteSpaces) { return const SizedBox.shrink(); } final day = !isLoading ? controller.getDay( DateTime(year, month, index - whiteSpaces + 1)) : null; // 提前计算颜色插值比例,全链路兜底 Color bgColor = Theme.of(context).shadowColor; if (day != null && day.habits.isNotEmpty) { final doneCount = controller.countHabitsDone(day); // 计算比例后强制限制在0-1区间,避免非法值 final ratio = (doneCount / day.habits.length).clamp(0.0, 1.0); bgColor = Color.lerp( Theme.of(context).shadowColor, Theme.of(context).primaryColor, ratio, )!; } return AnimatedContainer( duration: const Duration(milliseconds: 500), decoration: BoxDecoration( color: bgColor, borderRadius: BorderRadius.circular(5), ), ); }), ); }, )
排查延伸
如果修复后仍出现同类错误,可按以下顺序排查其他可能产生NaN/Infinity的位置:
- 检查
days、whiteSpaces变量的计算逻辑,是否存在除零、未初始化导致的非法值 - 检查GridView是否被嵌套在横向/竖向无边界约束的父组件中,导致布局计算出无穷大尺寸
- 检查AnimatedContainer是否存在动画起始/结束值设置为非法数值的情况
内容的提问来源于stack exchange,提问作者Sol
相关产品推荐
相关产品推荐

