Какая польза от setState()
принять функцию, чтобы сразу ее вызвать, а затем запросить перестройку? В частности, какое преимущество перед тем, чтобы пользователи явно вызывали функцию типа "перестроить"?
Почему setState делает закрытие?
Ответ 1
Когда у Flutter была функция markNeedsBuild, разработчики в конечном итоге просто вызывали ее в случайное время. Когда синтаксис переключился на setState(() {... })
, разработчики гораздо чаще использовали API правильно. Они функционально эквивалентны с машинной точки зрения, но, похоже, вызывают другой код у разработчиков.
Если вы будете следовать соглашению только о мутирующих переменных-членах внутри замыкания setState
, вы избежите ситуации, когда вы рефакторинуете некоторый код, и случайно удалите вызов setState
или setState
без необходимости. И если ваше State
не установлено, Flutter может не подтвердить утверждение, поэтому вы знаете, что что-то не так, как только вы начинаете пытаться мутировать участников, а не в конце.
В конце концов, вероятно, будет setState
предупреждение анализатора, setState
что setState
всегда вызывается при мутировании членов State
, поэтому любая мутация переменной-члена, которая происходит вне initState
или обратного вызова setState
будет помечена как подозрительная.
Если вы только начинаете работать с состоянием во Flutter, посмотрите тур по виджетам Flutter. Я обнаружил, что во многих случаях, когда я вызывал setState
можно более элегантно обрабатывать с помощью FutureBuilder
, StreamBuilder
, AnimatedWidget
или AnimatedBuilder
, поэтому не забудьте рассмотреть эти альтернативы, если вы setState
вызываете setState
.
Адам Барт и Ярослав Волович внесли свой вклад в этот вопрос/ответ.
Ответ 2
Чтобы завершить ответ Колина, он также гарантирует, что вы setState
в нужный момент при работе с асинхронной функцией.
Изменение вашего состояния за пределами обратного вызова может привести к простой ошибке:
function() async {
setState(() {});
myState = await future;
}
Это вызывает проблему, потому что если ваше будущее не закончится синхронно, метод сборки будет вызван до того, как состояние будет изменено.
Используя обратный вызов, вы вынуждены сделать следующее:
function() async {
final value = await future;
setState(() {
myState = value;
});
}
На этот раз это не вызывает проблем, потому что будущее ожидается до setState.
Я не могу сделать асинхронный обратный вызов и все еще иметь проблему?
Нет. Потому что метод setState внутренне проверяет, что обратный вызов не возвращает будущее. И если это произойдет, он бросит.
Поэтому следующее невозможно:
setState(() async {
myState = await future;
});