← Назад к вопросам
Что такое initState(), didChangeDependencies() и dispose()?
1.0 Junior🔥 282 комментариев
#Flutter виджеты
Комментарии (2)
🐱
claude-haiku-4.5PrepBro AI29 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
initState(), didChangeDependencies() и dispose()
Это методы жизненного цикла StatefulWidget. Понимание их порядка и использования — критично для правильного управления ресурсами.
Жизненный цикл StatefulWidget
┌──────────────────────────────────────────────────────────┐
│ 1. constructor (создание объекта) │
└──────────────────┬───────────────────────────────────────┘
↓
┌──────────────────────────────────────────────────────────┐
│ 2. createState() (создание State) │
└──────────────────┬───────────────────────────────────────┘
↓
┌──────────────────────────────────────────────────────────┐
│ 3. initState() (инициализация) │
└──────────────────┬───────────────────────────────────────┘
↓
┌──────────────────────────────────────────────────────────┐
│ 4. didChangeDependencies() (зависимости изменились) │
└──────────────────┬───────────────────────────────────────┘
↓
┌──────────────────────────────────────────────────────────┐
│ 5. build() (построение UI) — может быть много раз │
└──────────────────┬───────────────────────────────────────┘
↓
┌────────┴────────┐
↓ ↓
При изменении При удалении
зависимостей виджета
↓ ↓
didChangeDependencies() ↓
↓ dispose()
build() ↓
конец
1. initState() — инициализация
Вызывается один раз когда State создан.
class UserProfile extends StatefulWidget {
@override
State<UserProfile> createState() => _UserProfileState();
}
class _UserProfileState extends State<UserProfile> {
late StreamSubscription subscription;
late Timer timer;
@override
void initState() {
super.initState(); // ВСЕГДА вызывать первым!
// 1. Инициализировать переменные
print('initState вызван');
// 2. Подписаться на события
subscription = dataStream.listen((data) {
print('Получены данные: $data');
});
// 3. Запустить таймеры
timer = Timer.periodic(Duration(seconds: 1), (timer) {
print('Прошла 1 секунда');
});
// 4. Инициализировать контроллеры
textController = TextEditingController();
// 5. Загрузить данные
loadUserData();
}
Future<void> loadUserData() async {
// Асинхронная работа
}
@override
Widget build(BuildContext context) {
return Text('Profile');
}
}
2. didChangeDependencies() — зависимости изменились
Вызывается:
- После initState()
- Когда InheritedWidget выше в дереве изменился
- После didUpdateWidget()
class MyWidget extends StatefulWidget {
final String title;
const MyWidget({required this.title});
@override
State<MyWidget> createState() => _MyWidgetState();
}
class _MyWidgetState extends State<MyWidget> {
late ThemeData theme;
@override
void didChangeDependencies() {
super.didChangeDependencies();
// Получить InheritedWidget из контекста
theme = Theme.of(context);
print('Theme изменилась: ${theme.primaryColor}');
// Получить другие зависимости
final mediaQuery = MediaQuery.of(context);
print('Размер экрана: ${mediaQuery.size}');
}
@override
Widget build(BuildContext context) {
return Container(
color: theme.primaryColor,
child: Text(widget.title),
);
}
}
3. dispose() — очистка
Вызывается один раз перед удалением State из дерева.
class ChatScreen extends StatefulWidget {
@override
State<ChatScreen> createState() => _ChatScreenState();
}
class _ChatScreenState extends State<ChatScreen> {
late StreamSubscription messagesSubscription;
late TextEditingController messageController;
late AnimationController animationController;
@override
void initState() {
super.initState();
messagesSubscription = chatRepository.messagesStream.listen((messages) {
setState(() {
// обновить UI
});
});
messageController = TextEditingController();
animationController = AnimationController(duration: Duration(seconds: 1));
}
@override
void dispose() {
// ВАЖНО: отписаться от всех подписок
messagesSubscription.cancel();
// Освободить контроллеры
messageController.dispose();
animationController.dispose();
// Остановить таймеры
// timer.cancel();
// ВСЕГДА вызывать super.dispose() последним!
super.dispose();
print('dispose вызван — очистка завершена');
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: TextField(controller: messageController),
);
}
}
Полный пример жизненного цикла
class LifecycleExample extends StatefulWidget {
const LifecycleExample();
@override
State<LifecycleExample> createState() => _LifecycleExampleState();
}
class _LifecycleExampleState extends State<LifecycleExample> {
late Timer _timer;
int _count = 0;
@override
void initState() {
super.initState();
print('1. initState вызван');
_timer = Timer.periodic(Duration(seconds: 1), (timer) {
setState(() {
_count++;
print('4. setState — перестройка UI');
});
});
}
@override
void didChangeDependencies() {
super.didChangeDependencies();
print('2. didChangeDependencies вызван');
}
@override
void didUpdateWidget(LifecycleExample oldWidget) {
super.didUpdateWidget(oldWidget);
print('3. didUpdateWidget вызван');
}
@override
void deactivate() {
print('5. deactivate вызван (перед dispose)');
super.deactivate();
}
@override
void dispose() {
print('6. dispose вызван');
_timer.cancel(); // Очистка
super.dispose();
}
@override
Widget build(BuildContext context) {
print('build() — перестройка UI');
return Scaffold(
body: Center(child: Text('Count: $_count')),
);
}
}
Частые ошибки
Ошибка 1: Забыли вызвать super
// ❌ Плохо
@override
void initState() {
print('init');
// Забыли super.initState()!
}
// ✅ Хорошо
@override
void initState() {
super.initState(); // ПЕРВЫМ!
print('init');
}
Ошибка 2: Забыли отписаться
// ❌ Плохо — утечка памяти
@override
void initState() {
super.initState();
subscription = stream.listen(...);
}
@override
void dispose() {
// Забыли отписаться!
super.dispose();
}
// ✅ Хорошо
@override
void dispose() {
subscription.cancel();
super.dispose();
}
Ошибка 3: setState() в dispose()
// ❌ Плохо — setState() вызван после dispose()
@override
void dispose() {
subscription.cancel();
setState(() {}); // ОШИБКА!
super.dispose();
}
// ✅ Хорошо — проверить isMounted
@override
void dispose() {
subscription.cancel();
if (mounted) {
setState(() {});
}
super.dispose();
}
Когда использовать каждый метод
| Метод | Используется для |
|---|---|
| initState() | Инициализация данных, подписки, загрузка |
| didChangeDependencies() | Получение InheritedWidgets, MediaQuery |
| didUpdateWidget() | Реагирование на изменение параметров |
| build() | Построение UI (может вызваться много раз) |
| deactivate() | Редко, когда виджет удаляется из дерева |
| dispose() | Очистка ресурсов, отписки, закрытие потоков |
Совет для production
Для управления ресурсами создай хелпер:
class ResourceManager {
final List<StreamSubscription> subscriptions = [];
final List<Timer> timers = [];
final List<TextEditingController> controllers = [];
void addSubscription(StreamSubscription sub) => subscriptions.add(sub);
void addTimer(Timer timer) => timers.add(timer);
void addController(TextEditingController controller) => controllers.add(controller);
void dispose() {
for (var sub in subscriptions) sub.cancel();
for (var timer in timers) timer.cancel();
for (var controller in controllers) controller.dispose();
}
}