← Назад к вопросам

В каком порядке вызываются методы жизненного цикла State?

2.0 Middle🔥 221 комментариев
#Flutter виджеты#Архитектура Flutter

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI26 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Порядок вызова методов жизненного цикла State

Жизненный цикл State в Flutter — это чёткая последовательность методов, которые вызываются в определённом порядке от создания до удаления. Понимание этого критично для правильного управления ресурсами и инициализацией данных.

Полный порядок вызова методов

1. createState()

Первый вызываемый метод. Он находится в StatefulWidget и создаёт экземпляр State:

class MyApp extends StatefulWidget {
  @override
  State<MyApp> createState() => _MyAppState(); // Первый
}

2. initState()

Вызывается сразу после создания State. Это лучшее место для инициализации:

class _MyAppState extends State<MyApp> {
  late List<String> items;
  
  @override
  void initState() {
    super.initState(); // ВСЕГДА должен быть первой строкой
    print("initState called"); // Второй
    items = [];
    loadData(); // Инициализирующий код
  }
}

Важно: всегда вызывайте super.initState() первой строкой!

3. didChangeDependencies()

Вызывается сразу после initState() и каждый раз при изменении dependency (например, InheritedWidget):

@override
void didChangeDependencies() {
  print("didChangeDependencies called"); // Третий
  super.didChangeDependencies();
  
  // Например, получение темы из контекста
  final theme = Theme.of(context);
}

4. build()

Вызывается сразу после didChangeDependencies() и каждый раз при setState():

@override
Widget build(BuildContext context) {
  print("build called"); // Четвёртый (и многие разы)
  return Container();
}

Полная схема жизненного цикла

┌─────────────────────────────────────────┐
│  StatefulWidget (createState)           │ 1. createState()
└──────────────────┬──────────────────────┘
                   │
                   ▼
┌─────────────────────────────────────────┐
│  State (initState)                      │ 2. initState()
└──────────────────┬──────────────────────┘
                   │
                   ▼
┌─────────────────────────────────────────┐
│  didChangeDependencies()                │ 3. didChangeDependencies()
└──────────────────┬──────────────────────┘
                   │
                   ▼
┌─────────────────────────────────────────┐
│  build() ◄─ setState() ─ build()        │ 4. build() (многие разы)
└──────────────────┬──────────────────────┘
                   │
                   ▼
┌─────────────────────────────────────────┐
│  didUpdateWidget(oldWidget)             │ 5. didUpdateWidget() (если родитель изменился)
└──────────────────┬──────────────────────┘
                   │
                   ▼
┌─────────────────────────────────────────┐
│  deactivate() / dispose()               │ 6. deactivate() / 7. dispose()
└─────────────────────────────────────────┘

Детальное описание каждого метода

5. didUpdateWidget()

Вызывается, когда родительский widget перестроился и передал новые параметры:

@override
void didUpdateWidget(covariant MyApp oldWidget) {
  super.didUpdateWidget(oldWidget);
  print("didUpdateWidget called"); // Пятый
  
  // Сравнить старые и новые параметры
  if (widget.title != oldWidget.title) {
    loadNewData();
  }
}

6. deactivate()

Вызывается перед удалением State из дерева виджетов. Это может быть временно (например, при навигации):

@override
void deactivate() {
  print("deactivate called"); // Шестой
  // Очистить временные ресурсы
  super.deactivate();
}

7. dispose()

Вызывается после deactivate(). Это последний метод. Здесь нужно очищать ресурсы:

@override
void dispose() {
  print("dispose called"); // Седьмой - ПОСЛЕДНИЙ
  
  // Обязательно очищайте ресурсы
  _controller?.dispose();
  _streamSubscription?.cancel();
  
  super.dispose(); // ВСЕГДА в конце
}

Практический пример

class CounterApp extends StatefulWidget {
  @override
  State<CounterApp> createState() => _CounterAppState();
}

class _CounterAppState extends State<CounterApp> {
  late AnimationController _controller;
  int _counter = 0;
  
  @override
  void initState() {
    print("1. initState");
    super.initState();
    
    _controller = AnimationController(duration: Duration(seconds: 1), vsync: this);
    _loadInitialData();
  }
  
  @override
  void didChangeDependencies() {
    print("2. didChangeDependencies");
    super.didChangeDependencies();
  }
  
  @override
  void didUpdateWidget(CounterApp oldWidget) {
    print("3. didUpdateWidget");
    super.didUpdateWidget(oldWidget);
  }
  
  @override
  Widget build(BuildContext context) {
    print("4. build (called multiple times)");
    return Scaffold(
      body: Center(
        child: Text(_counter.toString()),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () => setState(() => _counter++),
        child: Icon(Icons.add),
      ),
    );
  }
  
  @override
  void deactivate() {
    print("5. deactivate");
    super.deactivate();
  }
  
  @override
  void dispose() {
    print("6. dispose");
    _controller.dispose();
    super.dispose();
  }
  
  Future<void> _loadInitialData() async {
    // Загрузка данных
  }
}

Важные моменты

✅ Что делать в каждом методе:

  • initState() — инициализировать переменные, подписаться на потоки, запустить таймеры
  • didChangeDependencies() — использовать контекст, получать данные из InheritedWidget
  • build() — ТОЛЬКО возвращать UI, не делать тяжёлые вычисления
  • didUpdateWidget() — реагировать на изменения параметров из родителя
  • dispose() — очищать контроллеры, отписываться от потоков, отменять таймеры

❌ Что НЕ делать:

  • Не вызывайте setState() в initState() (это приведёт к двойной перестройке)
  • Не используйте async/await напрямую в initState(), используйте Future
  • Не забывайте вызывать super методы
  • Не создавайте тяжёлые объекты в build()

Вывод

Понимание порядка вызова методов жизненного цикла State критично для:

  • Правильной инициализации данных
  • Эффективного управления ресурсами
  • Предотвращения утечек памяти
  • Написания стабильного и надёжного кода

Запомните: initState → didChangeDependencies → build → (setState) → didUpdateWidget → deactivate → dispose