Расскажи про жизненный цикл приложения Flutter

«Расскажи про жизненный цикл приложения Flutter» — вопрос из категории Жизненный цикл, который задают на 29% собеседований Flutter Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

В Flutter жизненный цикл можно рассматривать на двух уровнях: жизненный цикл виджета (Widget Lifecycle) и жизненный цикл всего приложения (App Lifecycle).

1. Жизненный цикл StatefulWidget

Это последовательность методов состояния виджета:

  • createState(): Flutter вызывает этот метод для создания объекта State.
  • initState(): Вызывается один раз после createState. Идеальное место для инициализации данных, подписки на Stream или инициализации контроллеров (например, AnimationController, ScrollController).
    @override
    void initState() {
    super.initState();
    _controller = AnimationController(
    vsync: this,
    duration: Duration(seconds: 1),
    );
    _setupData();
    }
  • didChangeDependencies(): Вызывается после initState и при каждом изменении зависимостей виджета (например, когда изменяется объект InheritedWidget, на который подписан этот виджет).
  • build(): Вызывается для отрисовки UI. Может вызываться многократно при setState() или изменениях зависимостей.
  • didUpdateWidget(oldWidget): Вызывается, когда родительский виджет перестраивается и передает новый виджет с тем же runtimeType. Позволяет сравнить старые и новые свойства (oldWidget vs widget).
  • setState(): Не метод жизненного цикла, а вызов, который уведомляет фреймворк об изменении внутреннего состояния и триггерит перестроение виджета через build().
  • deactivate(): Вызывается, когда виджет удаляется из дерева, но может быть позже повторно вставлен в другое место.
  • dispose(): Финальный метод. Вызывается, когда объект State удаляется навсегда. Здесь необходимо освобождать ресурсы: отменять анимации, закрывать потоки, отписываться от листенеров.
    @override
    void dispose() {
    _controller.dispose(); // Важно!
    _streamSubscription.cancel();
    super.dispose();
    }

2. Жизненный цикл приложения (App Lifecycle)

Отслеживается через миксин WidgetsBindingObserver. Состояния:

  • resumed: Приложение видимо и взаимодействует с пользователем.
  • inactive: Приложение неактивно (например, во время входящего звонка на iOS или при переключении между приложениями). Состояние может быть кратковременным.
  • paused: Приложение не видимо пользователю (свернуто или перекрыто другим приложением).
  • detached: Приложение полностью завершено (на некоторых платформах).

Пример использования:

class _MyHomePageState extends State<MyHomePage> with WidgetsBindingObserver {
  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance.addObserver(this);
  }

  @override
  void dispose() {
    WidgetsBinding.instance.removeObserver(this);
    super.dispose();
  }

  @override
  void didChangeAppLifecycleState(AppLifecycleState state) {
    switch (state) {
      case AppLifecycleState.resumed:
        print('App resumed: restart animations, refresh data');
        _controller.forward();
        break;
      case AppLifecycleState.paused:
        print('App paused: pause animations, save state');
        _controller.stop();
        _saveCurrentState();
        break;
      // Обработка других состояний
    }
  }
}

Понимание жизненного цикла критично для управления ресурсами, подписками и состоянием UI, что напрямую влияет на производительность и отсутствие утечек памяти.