Ответ
Нет, initState() вызывается не всегда. Это метод жизненного цикла, который вызывается ровно один раз при первом встраивании (insert) объекта State в дерево виджетов.
Когда initState() НЕ вызывается:
- Если объект
Stateбыл создан, но соответствующийStatefulWidgetникогда не был добавлен в дерево (например, из-за условного оператораif (false) MyWidget()). - При горячей перезагрузке (Hot Reload) состояние сохраняется, и
initState()не вызывается заново. - Если виджет был удален из дерева и затем снова добавлен с тем же ключом (
key), Flutter может переиспользовать существующий объектState, иinitState()вызван не будет.
Типичный сценарий использования в Flutter:
class _MyHomePageState extends State<MyHomePage> {
late StreamSubscription<int> _streamSubscription;
final _scrollController = ScrollController();
ComplexData? _cachedData;
@override
void initState() {
super.initState(); // Всегда вызывайте super.initState() первым!
print('initState: Виджет встроен в дерево.');
// Идеальное место для:
// 1. Инициализации final/ late final полей, зависящих от widget.
_cachedData = ComplexData(widget.initialParam);
// 2. Подписки на Stream или Listenable.
_streamSubscription = myStream.listen(_handleData);
_scrollController.addListener(_onScroll);
// 3. Запуска одноразовых асинхронных операций (но не async/await).
WidgetsBinding.instance.addPostFrameCallback((_) {
// Код, который должен выполниться после первого построения кадра.
});
_loadInitialData(); // Метод, который запускает Future.
}
Future<void> _loadInitialData() async {
final data = await Api.fetchData();
setState(() => _cachedData = data);
}
@override
void dispose() {
// Все, что создано в initState, должно быть очищено в dispose.
_streamSubscription.cancel();
_scrollController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: ListView(
controller: _scrollController,
children: [
Text('Данные: ${_cachedData?.value}'),
],
),
);
}
}
Гарантия: Если виджет был вставлен в дерево и у него вызвался build(), то initState() был вызван ранее.