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

Flutter使用maze包开发迷宫游戏 计时存SharedPreferences为00:00

问题根源

你存到SharedPreferences里始终是00:00的核心原因是Dart闭包的变量捕获机制:

  • 第一次build渲染Maze组件时,onFinish回调就被创建了,这时候闭包里捕获的minutes、seconds是基于初始值duration = Duration()计算出来的00、00
  • 后续计时器每秒触发setState重建页面时,UI上显示的计时数值会更新,但Maze组件不会自动替换持有的旧onFinish回调,回调里始终保存着第一次生成时捕获的0分0秒值
  • 额外逻辑问题:你原来的代码先调用reset()再存值,后续如果给reset加了重置duration的逻辑,会直接把时长清零,更拿不到正确结果。
修复方案
  • 不要在onFinish回调里使用build方法内生成的临时minutes、seconds变量,回调触发时直接读取State中持有的最新duration值做格式化
  • 调整执行顺序:先读取时长、写入SharedPreferences,再取消计时器
  • 可选优化:把格式化数字的twoDigits方法从build方法中挪到State的成员位置,避免每次重建页面都重复声明函数

修正后的核心代码

修改onFinish回调逻辑如下即可:

Maze(
  player: MazeItem(
    'assets/start.png',
    ImageType.asset,
  ),
  columns: 7,
  rows: 7,
  wallThickness: 3.0,
  wallColor: const Color(0xFF81b29a),
  finish: MazeItem(
    'assets/finish.png',
    ImageType.asset,
  ),
  onFinish: () async {
    // 直接读取当前最新的duration值计算,不依赖build时生成的旧临时变量
    String twoDigits(int n) => n.toString().padLeft(2, '0');
    final currentMinutes = twoDigits(duration.inMinutes.remainder(60));
    final currentSeconds = twoDigits(duration.inSeconds.remainder(60));
    
    // 先写入存储
    final prefs = await SharedPreferences.getInstance();
    await prefs.setString("mazeTimer", '$currentMinutes:$currentSeconds');
    
    // 存值完成后再停止计时器
    timer?.cancel();
  },
)

如果后续需要实现重开迷宫的功能,再给reset方法补全重置duration的逻辑即可,注意重置操作必须放在存值完成之后。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 23:30:52