Ответ
Метод dispose() вызывается, когда объект State окончательно и безвозвратно удаляется из дерева виджетов. Это точка очистки ресурсов, чтобы избежать утечек памяти.
Конкретные случаи вызова dispose():
- При удалении виджета из дерева навсегда (например,
Navigator.pushReplacementзаменяет текущий экран). - Когда родительский виджет перестраивается и больше не включает данный
StatefulWidget. - При использовании
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() после этого выбросит исключение.