Когда вызывается метод dispose() у State в Flutter?

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

Ответ

Метод dispose() вызывается, когда объект State окончательно и безвозвратно удаляется из дерева виджетов. Это точка очистки ресурсов, чтобы избежать утечек памяти.

Конкретные случаи вызова dispose():

  1. При удалении виджета из дерева навсегда (например, Navigator.pushReplacement заменяет текущий экран).
  2. Когда родительский виджет перестраивается и больше не включает данный StatefulWidget.
  3. При использовании GlobalKey и перемещении виджета в другое место дерева с другим ключом.

Что обязательно нужно освобождать в dispose():

class _MyPlayerState extends State<MyPlayer> {
  late AnimationController _animationController;
  late StreamSubscription<int> _timerSubscription;
  Timer? _periodicTimer;
  final _scrollController = ScrollController();

  @override
  void initState() {
    super.initState();
    _animationController = AnimationController(vsync: this, duration: Duration(seconds: 1));
    _timerSubscription = Stream.periodic(Duration(seconds: 1)).listen((_) {});
    _periodicTimer = Timer.periodic(Duration(seconds: 1), (_) {});
    _scrollController.addListener(() {});
  }

  @override
  void dispose() {
    // 1. Контроллеры анимаций (обязательно, т.к. они требуют TickerProvider)
    _animationController.dispose();

    // 2. Подписки на стримы
    _timerSubscription.cancel();

    // 3. Таймеры
    _periodicTimer?.cancel();

    // 4. Контроллеры скролла, текста и т.п.
    _scrollController.dispose();

    // Вызов super.dispose() ВСЕГДА в конце
    super.dispose();
  }
}

Важно: После вызова dispose() объект State больше не может быть использован. Любая попытка вызвать setState() после этого выбросит исключение.