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

Flutter数独游戏JSON存储空值异常:实现继续游戏功能遇问题

解决Flutter数独游戏序列化空值异常问题

第一步:修正SudokuCell模型的JSON序列化逻辑

空值异常多数源于模型类toJson方法未处理null字段,需确保所有可能为空的字段都有兜底处理:

class SudokuCell {
  final int? value;
  final bool isFixed;
  final List<int> notes;

  SudokuCell({this.value, required this.isFixed, required this.notes});

  // 处理空值的toJson方法
  Map<String, dynamic> toJson() {
    return {
      'value': value ?? 0, // 空值替换为业务允许的默认值,比如0
      'isFixed': isFixed,
      'notes': notes,
    };
  }

  // 同步修正反序列化逻辑
  factory SudokuCell.fromJson(Map<String, dynamic> json) {
    return SudokuCell(
      value: json['value'] == 0 ? null : json['value'],
      isFixed: json['isFixed'],
      notes: List<int>.from(json['notes']),
    );
  }
}

第二步:完善GameController的序列化逻辑

确保控制器中存储的二维单元格数组无null元素,且整体序列化逻辑覆盖所有字段:

class GameController {
  late List<List<SudokuCell>> grid;
  String? currentDifficulty;
  int? elapsedTime;

  // 序列化游戏数据
  Map<String, dynamic> toJson() {
    final gridJson = grid.map((row) => row.map((cell) => cell.toJson()).toList()).toList();
    return {
      'grid': gridJson,
      'currentDifficulty': currentDifficulty ?? 'easy', // 空值兜底
      'elapsedTime': elapsedTime ?? 0, // 空值兜底
    };
  }

  // 反序列化游戏数据
  factory GameController.fromJson(Map<String, dynamic> json) {
    final controller = GameController();
    controller.grid = (json['grid'] as List)
        .map((rowJson) => (rowJson as List)
            .map((cellJson) => SudokuCell.fromJson(cellJson))
            .toList())
        .toList();
    controller.currentDifficulty = json['currentDifficulty'];
    controller.elapsedTime = json['elapsedTime'];
    return controller;
  }
}

第三步:SharedPreferences存储时的异常防护

存储前确保序列化后的JSON无null值,同时捕获序列化/反序列化异常便于排查:

// 存储游戏数据
Future<void> saveGame(GameController controller) async {
  final prefs = await SharedPreferences.getInstance();
  try {
    final gameJson = jsonEncode(controller.toJson());
    await prefs.setString('saved_game', gameJson);
  } catch (e) {
    print('序列化失败:$e');
  }
}

// 读取游戏数据
Future<GameController?> loadGame() async {
  final prefs = await SharedPreferences.getInstance();
  final gameJson = prefs.getString('saved_game');
  if (gameJson == null) return null;
  try {
    final gameMap = jsonDecode(gameJson) as Map<String, dynamic>;
    return GameController.fromJson(gameMap);
  } catch (e) {
    print('反序列化失败:$e');
    return null;
  }
}

快速排查点

  • 单独测试单个SudokuCell的序列化:调用jsonEncode(SudokuCell(...).toJson()),定位具体抛出异常的字段
  • 检查字段nullable修饰:确保非必填字段都标记为int?/String?,避免未初始化的非空字段导致报错
  • 验证二维数组完整性:确保GameController.grid中没有null元素,初始化时要填满所有单元格

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 03:45:46