У меня есть приложение тральщика, которое содержит одну панель приложений (с кнопкой перезапуска смайлика), один bottomAppBar (с кнопками уровня) и одну доску (которая, в свою очередь, имеет поля).
Я использую setState()
установить выигрыш и попытаться использовать его для установки уровня игры через _level
. Но к тому времени, когда виджет перестраивается (с помощью setState
, запускаемого одной из кнопок уровня), переменная _level
снова становится равной нулю.
Нужно ли перемещать состояние _level вверх в дерево виджетов? Имеет ли это какое-то отношение к используемому виджету LayoutBuilder?
class MinesweeperApp extends StatefulWidget {
@override
_MinesweeperAppState createState() => _MinesweeperAppState();
}
class _MinesweeperAppState extends State<MinesweeperApp> {
bool _win;
Board _board;
Level _level;
Board _getBoard(
double width,
double height,
) {
if (_board == null) {
int qtyOfColumns = (width / (width * 0.09)).floor();
double fieldSize = width / qtyOfColumns;
int qtyOfRows = (height / fieldSize).floor();
_board = Board(
qtyOfRows: qtyOfRows, qtyOfColumns: qtyOfColumns, level: _level==null ? Level.medium : _level);
}
return _board;
}
@override
void initState() {
_level = Level.medium;
super.initState();
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
bottomNavigationBar: BottomAppBar(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
FlatButton(
child: Text('EASY'),
onPressed: () {
_onRestart(Level.easy);
},
),
FlatButton(
child: Text('MEDIUM'),
onPressed: () {
_onRestart(Level.medium);
},
),
FlatButton(
child: Text('HARD'),
onPressed: () {
_onRestart(Level.hard);
},
),
],
),
),
appBar: MinesweeperAppBar(
win: _win,
onRestart: ()=>_onRestart(_level),
),
body: Center(
child: LayoutBuilder(
builder: (context, constraints) {
return BoardWidget(
board: _getBoard( constraints.maxWidth, constraints.maxHeight),
onOpen: _open,
onToggleMarked: _toggleMarked,
);
},
),
),
),
);
}
void _open(Field field) {
setState(() {
if (_win != null) {
return;
}
try {
field.open();
if (_board.solved) {
_win = true;
}
} on ExplosionException {
_win = false;
_board.revealMines();
}
});
}
void _toggleMarked(Field field) {
if (_win != null) {
return;
}
setState(() {
field.toggleMarked();
if (_board.solved) {
_win = true;
}
});
}
void _onRestart(Level level) {
setState(() {
_level = level;
_win = null;
_board.restartGame();
});
}
}
Кроме того, кто-нибудь знает источник для изучения такого поведения setState (простого, так как я не разбираюсь в технических деталях) )? Я пытаюсь обдумать эту концепцию.