Flutter. "setState() called during build" error

Ошибка "setState() called during build" в Flutter возникает, когда вы вызываете setState()
во время перестройки дерева виджетов, что может привести к неожиданному поведению или бесконечным циклам.
Вот как можно решить эту проблему:
Возможные причины и решения:
-
Вызов
setState
внутри метода build:- Убедитесь, что вы не вызываете
setState()
непосредственно внутри методаbuild()
.setState
должен вызываться в ответ на взаимодействие пользователя или асинхронное событие (например, сетевой запрос).Пример:
@override Widget build(BuildContext context) { // Неправильно: setState вызывается напрямую в build if (someCondition) { setState(() { // изменение состояния }); } return Scaffold( // код UI ); }
Решение: Перенесите изменение состояния в подходящее место, например, в обработчик события или после получения результата асинхронной операции.
- Убедитесь, что вы не вызываете
-
Асинхронные изменения состояния:
- Если вы вызываете
setState()
в асинхронной операции, такой какFutureBuilder
или внутри методаthen()
, убедитесь, что виджет не перестраивается в тот момент, когда вызываетсяsetState
.
Пример:Future<void> someAsyncFunction() async { final result = await someFuture; setState(() { // обновление состояния здесь }); }
Решение: Убедитесь, что
setState
вызывается после завершения асинхронной операции, но вне контекста методаbuild
.
- Если вы вызываете
-
Таймеры или слушатели событий:
Если вы используетеTimer
,AnimationController
или другие слушатели событий, убедитесь, чтоsetState()
вызывается в ответ на событие, но не во время перестройки виджета.
Пример:Timer.periodic(Duration(seconds: 1), (timer) { setState(() { // обновление состояния }); });
Решение: Используйте их безопасным образом, проверяя, что виджет всё ещё существует (mounted), или корректно отменяйте таймеры/слушатели, когда виджет уничтожается.
Резюме решений:
- Не вызывайте
setState()
внутри методаbuild()
. - Вызывайте
setState()
после завершения асинхронных операций. - Для периодических изменений состояния (таймеры, анимации) убедитесь, что виджет всё ещё существует перед вызовом
setState()
.