Flutter空安全迁移报错:'Null'不是'Cpu'类型的子类型
问题根因
升级Flutter空安全版本后出现type 'Null' is not a subtype of type 'Cpu'错误,核心是两处空安全适配遗漏:
- 跳转PVC模式
/match路由时,传入的arguments仅包含mode和cpu字段,未传cpu2字段;但MatchPage构造函数中cpu2被标记为必填非空Cpu类型,路由解析时args['cpu2']取值为null,null被强转为非空Cpu类型直接触发类型不匹配错误。 - 状态类
_MatchPageState中turn、winner字段使用late修饰但未在初始化阶段赋值,后续运行会触发延迟初始化异常。
修复步骤
1. 调整MatchPage的参数类型
将非全场景必填的cpu2改为可空类型,移除必填标记,适配PVC、PVP模式不需要传入第二个AI的场景:
class MatchPage extends StatefulWidget { final Mode mode; final Cpu cpu; final Cpu? cpu2; // 改为可空类型,仅DEMO双AI对战场景需要传值 const MatchPage({ Key? key, required this.mode, required this.cpu, this.cpu2, // 移除required限定 }) : super(key: key); @override _MatchPageState createState() => _MatchPageState(); }
2. 修正状态类字段的空安全声明
把初始值本就为null的winner改为可空类型,避免不符合业务逻辑的空安全声明:
class _MatchPageState extends State<MatchPage> with TickerProviderStateMixin { final board = Board(); late Player turn; Player? winner; // 原late Player winner改为可空类型,游戏初始无赢家时值为null // ... 其余代码保持不变
3. 补全初始化逻辑,调整可空字段的访问
在initState中给turn设置默认初始值,访问DEMO模式下的cpu2时添加非空断言(跳转DEMO路由时必须同时传入两个AI实例,此时cpu2不可能为null):
@override void initState() { super.initState(); turn = Player.RED; // 默认红方先手,给late字段赋初始值 winner = null; if (widget.mode == Mode.PVC && turn == widget.cpu.player) { cpuMove(widget.cpu); } else if (widget.mode == Mode.DEMO) { if (turn == widget.cpu.player) { cpuMove(widget.cpu); } else { cpuMove(widget.cpu2!); // 加非空断言!,DEMO模式下cpu2必传 } } }
4. 修正其余位置的可空字段访问
找到cpuMove方法中DEMO逻辑分支调用cpu2的位置,同样添加非空断言:
void cpuMove(Cpu cpu) async { int col = await cpu.chooseCol(board); putChip(col); if (winner == null && widget.mode == Mode.DEMO) { if (turn == widget.cpu.player) { cpuMove(widget.cpu); } else { cpuMove(widget.cpu2!); // 加非空断言 } } }
额外说明
如果后续需要适配PVP模式,可以把cpu字段也调整为可空类型,在PVP模式下不需要传入AI实例,对应判断逻辑加空判断即可。跳转DEMO模式时,记得在arguments里同时传入cpu和cpu2两个AI实例,避免触发非空断言错误。
内容的提问来源于stack exchange,提问作者Nitneuq
相关产品推荐
相关产品推荐

