Flutter中逻辑应该放在哪里?数独开发顶层逻辑如何获取Square状态
Flutter数独全局状态管理解决方案
核心改造方向(推荐):状态上移到全局逻辑层统一管理
你当前已经在使用LogicalBoard作为全局通知层,只需要把分散在各个Square组件内部的状态全部上移到LogicalBoard中存储即可,完全不需要更换整体架构,改造成本极低:
- 在
LogicalBoard中新增长度为81的状态列表,比如List<SquareData> squareStateList,每个SquareData实例存储对应单元格的所有状态:mainNumber、9个小数字显隐状态、选中状态等 - 将
Square组件改为无状态组件,所有渲染需要的状态都从LogicalBoard.squareStateList[widget.squareIndex]中读取 - 所有用户交互触发的状态修改,都直接调用
LogicalBoard的方法修改对应下标的SquareData,再触发全局通知更新即可 - 顶层游戏逻辑需要查询任意单元格状态时,直接读取
LogicalBoard.squareStateList对应下标的数据即可,后续做全局校验、悔棋、答案提示等功能都非常方便
临时方案(不推荐长期使用):用GlobalKey获取组件State
如果你不想改动现有Square自己存状态的逻辑,也可以通过Flutter的GlobalKey直接获取每个Square的State实例读取状态:
- 顶层创建长度为81的GlobalKey列表:
List<GlobalKey<_SquareState>> squareKeys = List.generate(81, (index) => GlobalKey()); - 初始化每个
Square时,将对应下标的key传给Square的key参数 - 需要读取状态时,直接通过
squareKeys[index].currentState即可拿到对应单元格的内部状态,注意如果要读取私有属性,需要给_SquareState类的属性新增公开getter,或者把属性的下划线去掉改为公开
现有代码优化提示
你当前把监听器注册逻辑写在了build方法中,每次组件重绘都会重复添加监听器,会触发内存泄漏和逻辑重复执行的问题,需要把监听器注册逻辑移到initState中,dispose时移除:
class _SquareState extends State<Square> { int _mainNumber = 0; bool showEdit1 = false; bool showEdit2 = false; bool showEdit3 = false; bool showEdit4 = false; bool showEdit5 = false; bool showEdit6 = false; bool showEdit7 = false; bool showEdit8 = false; bool showEdit9 = false; bool _selected = false; bool _selectedCollection = false; @override void initState() { super.initState(); LogicalBoard.numberButtonNotifier.addListener(_onNumberUpdate); LogicalBoard.selectionNotifier.addListener(_onSelectionUpdate); } @override void dispose() { LogicalBoard.numberButtonNotifier.removeListener(_onNumberUpdate); LogicalBoard.selectionNotifier.removeListener(_onSelectionUpdate); super.dispose(); } void _onNumberUpdate() { if(LogicalBoard.selectedSquare?.squareIndex == widget.squareIndex){ setState(() { _mainNumber = LogicalBoard.numberLastClicked; }); } } void _onSelectionUpdate() { setState(() { _selected = LogicalBoard.selectedSquare?.squareIndex == widget.squareIndex; _selectedCollection = LogicalBoard.selectedSquare?.squareIndex == widget.squareIndex || LogicalBoard.selectedSquare?.rowIndex == widget.rowIndex || LogicalBoard.selectedSquare?.colIndex == widget.colIndex || LogicalBoard.selectedSquare?.boxIndex == widget.boxIndex; }); } @override Widget build(BuildContext context) { // 原build逻辑移除addListener部分,其余保持不变 return Material( child: InkWell( onTap: () => LogicalBoard.selectionNotifier .setSelectedSquare(widget.squareIndex), child: Container( padding: const EdgeInsets.all(2.0), color: _selected ? Theme.of(context).errorColor : Theme.of(context).primaryColorDark, width: 52.0, height: 52.0, child: Container( padding: _mainNumber == 0 ? const EdgeInsets.fromLTRB(2.0, 8.0, 2.0, 2.0) : const EdgeInsets.all(0.0), color: _selectedCollection ? Theme.of(context).backgroundColor : Theme.of(context).primaryColor, width: 48.0, height: 48.0, child: _mainNumber != 0 ? Center( child: Text( _mainNumber.toString(), style: Theme.of(context).textTheme.headline3, )) : Column(mainAxisSize: MainAxisSize.min, children: [ Flexible( child: Row( mainAxisSize: MainAxisSize.min, children: [ Flexible( child: Text( showEdit1 ? "1" : "", style: Theme.of(context).textTheme.bodyText2, )), Flexible( child: Text( showEdit2 ? "2" : "", style: Theme.of(context).textTheme.bodyText2, )), Flexible( child: Text( showEdit3 ? "3" : "", style: Theme.of(context).textTheme.bodyText2, )) ])), Flexible( child: Row( mainAxisSize: MainAxisSize.min, children: [ Flexible( child: Text( showEdit4 ? "4" : "", style: Theme.of(context).textTheme.bodyText2, )), Flexible( child: Text( showEdit5 ? "5" : "", style: Theme.of(context).textTheme.bodyText2, )), Flexible( child: Text( showEdit6 ? "6" : "", style: Theme.of(context).textTheme.bodyText2, )) ])), Flexible( child: Row( mainAxisSize: MainAxisSize.min, children: [ Flexible( child: Text( showEdit7 ? "7" : "", style: Theme.of(context).textTheme.bodyText2, )), Flexible( child: Text( showEdit8 ? "8" : "", style: Theme.of(context).textTheme.bodyText2, )), Flexible( child: Text( showEdit9 ? "9" : "", style: Theme.of(context).textTheme.bodyText2, )) ])) ])), ))); } }
内容的提问来源于stack exchange,提问作者user3665287
相关产品推荐
相关产品推荐

