我想用Flutter写一个小的棋盘游戏。我有关卡的初始状态。简而言之,关卡类包括棋盘类,其中包括许多带有坐标的瓦片。示例如下:
const levels = [
Level(
number: 1,
board: Board(
cols: 3,
rows: 1,
tiles: [
Tile(
id: 1,
isExists: true,
isFilled: true,
coordinates: Coordinates(x: 0, y: 0),
),
Tile(
id: 2,
isExists: true,
isFilled: true,
coordinates: Coordinates(x: 0, y: 1),
),
Tile(
id: 3,
isExists: true,
isFilled: false,
coordinates: Coordinates(x: 0, y: 2),
),
],
),
),
]
**主要问题:**当玩家在游戏场上做出任何动作时,关卡的初始状态会发生变化。特别是“isFilled”字段会发生变化。之后,如果您转到主菜单并再次选择关卡,我们将看到之前发生变化的状态。有人能给我演示一下如何使用ChangeNotifier实现不可变的关卡数组结构吗?
我试着通过ChangeNotifierProvider和Consumer来实现它。也许我需要使用另一个状态管理系统,比如Bloc或类似的东西?我也试着用Level选项复制主对象,但没有帮助。
UPD:简单的addCol函数。
播放会话屏幕组件:
final Board board = Board(
cols: widget.level.board.cols,
rows: widget.level.board.rows,
tiles: widget.level.board.tiles,
winCondition: widget.level.board.winCondition,
);
return MultiProvider(
providers: [
ChangeNotifierProvider(
create: (context) => BoardState(
board: board,
),
),
],
child: Scaffold(
Consumer<BoardState>(
builder: (context, boardState, child) => Container(
child: Column(
children: [
Text(boardState.board.cols.toString()),
InkWell(
onTap: () =>
Provider.of<BoardState>(context, listen: false)
.addCol(),
child: Text('Add col'),
),
],
),
),
),
),
);
主板状态组件:
class BoardState extends ChangeNotifier {
final Board board;
BoardState({
required this.board,
});
int get cols => board.cols;
void addCol() {
board.cols++;
notifyListeners();
}
}
主板类别:
class Board {
final int cols;
final int rows;
final List<Tile> tiles;
final int winCondition;
const Board({
required this.cols,
required this.rows,
required this.tiles,
required this.winCondition,
});
}
class Board {
late int cols;
final int rows;
final List<Tile> tiles;
final int winCondition;
Board(
this.cols, {
required this.rows,
required this.tiles,
required this.winCondition,
});
}
1条答案
按热度按时间2wnc66cl1#
也许我需要使用另一个状态管理系统,像Bloc或类似的东西?
Riverpod是在考虑到不可变性情况下构建的,如果您想给予的话。
也就是说,由于
Board
被标记为final
,所以board.cols++
的内容将不起作用。ChangeNotifier
可以很好地处理可变数据。只要让你的Board
为非final
,并用一个新的Board
替换它,其中包含除了更新的cols
之外的所有旧属性,如下所示:这意味着你的模型需要实现某种
copyWith
函数。如果你使用@freezed
,你可以这样实现:前一个将免费为您提供
.copyWith
(以及更多)。这应该会消除替换旧数据的痛苦。