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

从其他页面启动Flutter滑块拼图项目时出现两类异常问题

解决Flutter滑块拼图项目的两个启动异常

咱们来一步步拆解你遇到的这两个异常,从根源上解决问题:

1. Unsupported operation: Infinity or NaN toInt 异常

这个错误的栈跟踪指向了语义化节点的尺寸计算,说白了就是你的界面里某个Widget的尺寸算出了无限大或者非数值,转成整数的时候直接崩了。

从你贴的代码来看,可能的诱因有两个:

  • 虽然你给rows和columns设了默认值3,但如果外部传参时不小心传了0,后续计算拼图块尺寸时就会出现除以0的情况,直接产出NaN;
  • 拼图容器没有明确的尺寸约束,导致子Widget的尺寸计算溢出成Infinity。

修复步骤:

  • 给行列数加个校验,确保永远大于0,在PuzzlePage的构造函数里加断言:
PuzzlePage({int columns = 3, int rows = 3}) 
  : columns = columns ?? 3, 
    rows = rows ?? 3 {
  assert(columns > 0, "列数必须大于0");
  assert(rows > 0, "行数必须大于0");
}
  • 给拼图容器加明确的尺寸约束,比如用屏幕尺寸的80%作为拼图大小,避免无限尺寸:
// 在_PuzzleHome的build方法里添加约束
@override
Widget build(BuildContext context) {
  final screenSize = MediaQuery.of(context).size;
  final puzzleSize = min(screenSize.width, screenSize.height) * 0.8;
  return Container(
    width: puzzleSize,
    height: puzzleSize,
    // 这里放你的拼图内容
  );
}

2. NoSuchMethodError: The getter '_duration' was called on null 异常

这个错误很直白:你调用某个对象的_duration属性时,那个对象是null。结合你的代码,问题大概率出在PuzzleAnimator的初始化上。

你现在是在_PuzzleHome的createState里直接new了PuzzleAnimator并传给PuzzleHomeState,如果PuzzleAnimator的初始化依赖上下文或者需要异步操作,这种写法很容易导致实例初始化不完整,后续用的时候就成null了;另外,如果PuzzleHomeState没有正确持有这个实例,也可能被回收成null。

修复步骤:

  • 把PuzzleAnimator的初始化移到PuzzleHomeState的initState里,不要在createState里传:
class _PuzzleHome extends StatefulWidget {
  final int _rows, _columns;
  const _PuzzleHome(this._rows, _columns, {Key key}) : super(key: key);

  @override
  PuzzleHomeState createState() => PuzzleHomeState();
}

class PuzzleHomeState extends State<_PuzzleHome> {
  PuzzleAnimator _animator;

  @override
  void initState() {
    super.initState();
    // 在这里初始化动画器,确保上下文准备好
    _animator = PuzzleAnimator(widget._columns, widget._rows);
  }

  // 后续使用_animator前可以加个判空,或者确保初始化完成
}
  • 检查PuzzleAnimator的实现,确保_duration在初始化时就被赋值,别搞延迟初始化导致null:
class PuzzleAnimator {
  final int columns;
  final int rows;
  Duration _duration;

  // 用初始化列表直接赋值
  PuzzleAnimator(this.columns, this.rows) : _duration = Duration(milliseconds: 300);

  // 或者在构造函数里初始化
  // PuzzleAnimator(this.columns, this.rows) {
  //   _duration = Duration(milliseconds: 300);
  // }
}

额外的代码小问题

  • 你的PuzzlePage里的_context变量没赋值,在didUpdateWidget里调用AppBuilder.of(_context)肯定会报错,记得在build方法里赋值:
@override
Widget build(BuildContext context) {
  _context = context; // 在这里把上下文存起来
  return AppBuilder(
    builder: (context) {
      return _PuzzleHome(widget.rows, widget.columns);
    });
}
  • WidgetsBindingObserver的注册漏了,在PuzzlePageState的initState里加上:
@override
void initState() {
  super.initState();
  WidgetsBinding.instance.addObserver(this); // 注册观察者
}

内容的提问来源于stack exchange,提问作者George John

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.13 08:28:55