Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI26 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Когда срабатывает activate() в Flutter
activate() — это lifecycle метод State widget, который срабатывает в специфических моментах жизненного цикла компонента.
1. Основное определение
class MyWidget extends StatefulWidget {
@override
State<MyWidget> createState() => _MyWidgetState();
}
class _MyWidgetState extends State<MyWidget> {
@override
void initState() {
super.initState();
print('initState called');
}
@override
void activate() {
super.activate();
print('activate called');
}
@override
void deactivate() {
super.deactivate();
print('deactivate called');
}
@override
void dispose() {
super.dispose();
print('dispose called');
}
@override
Widget build(BuildContext context) {
return Container();
}
}
2. Когда именно срабатывает activate()
activate() вызывается в двух случаях:
a) После initState при первой вставке виджета в tree
initState() → activate() → build()
b) Когда State переиспользуется из другой позиции в widget tree
Это происходит, когда виджет был деактивирован (deactivate), но затем переиспользуется:
deactivate() → activate() → build()
3. Полный lifecycle flow
Сценарий 1: Нормальная жизнь виджета
1. createState() - создание State
2. initState() - инициализация (один раз)
3. activate() - активация (может быть несколько раз)
4. build() - отрисовка
5. didUpdateWidget() - когда parent widget изменился
6. build() - перерисовка
7. deactivate() - деактивация
8. dispose() - очистка (финальный)
Сценарий 2: Перемещение виджета в tree
// Первое создание
creatState() → initState() → activate() → build()
// Перемещение позиции в tree
deactivate() → activate() → build()
// Удаление из tree
deactivate() → dispose()
4. Практический пример: GlobalKey и переиспользование State
Самый наглядный пример — использование GlobalKey, когда State переиспользуется:
class ParentWidget extends StatefulWidget {
@override
State<ParentWidget> createState() => _ParentWidgetState();
}
class _ParentWidgetState extends State<ParentWidget> {
final GlobalKey<_ChildWidgetState> childKey =
GlobalKey<_ChildWidgetState>();
bool swapPosition = false;
@override
Widget build(BuildContext context) {
return Column(
children: [
// Меняем позицию child виджета
if (!swapPosition)
ChildWidget(key: childKey, name: 'First'),
SizedBox(height: 20),
if (swapPosition)
ChildWidget(key: childKey, name: 'First'),
ElevatedButton(
onPressed: () {
setState(() => swapPosition = !swapPosition);
// При нажатии вызывается:
// deactivate() → activate() → build()
},
child: Text('Swap Position'),
),
],
);
}
}
class ChildWidget extends StatefulWidget {
final String name;
const ChildWidget({Key? key, required this.name}) : super(key: key);
@override
State<ChildWidget> createState() => _ChildWidgetState();
}
class _ChildWidgetState extends State<ChildWidget> {
late String internalState;
@override
void initState() {
super.initState();
internalState = 'initialized';
print('initState');
}
@override
void activate() {
super.activate();
print('activate - State переиспользуется');
// internalState сохранён! Не очищается
}
@override
void deactivate() {
super.deactivate();
print('deactivate - State снимается с tree');
}
@override
Widget build(BuildContext context) {
return Text('${widget.name}: $internalState');
}
}
5. Когда activate() НЕ вызывается
activate() НЕ срабатывает при:
- Просто setState() в том же виджете
- didUpdateWidget() (это другой callback)
- Изменении build() без изменения позиции в tree
- Пересоздании State через новый ключ
// НЕ вызовет activate()
setState(() {
counterValue++;
});
// ВЫЗОВЕТ activate() если GlobalKey переместился в tree
final key = GlobalKey<_MyState>();
// Сначала: MyWidget(key: key) на позиции 0
// Потом: MyWidget(key: key) на позиции 1
// → deactivate() → activate()
6. Разница между initState и activate
| Метод | Вызывается | Количество | Состояние |
|---|---|---|---|
| initState() | При создании State | 1 раз | Впервые, инициализация |
| activate() | При добавлении в tree | 1+ раз | Может быть несколько раз |
| didUpdateWidget() | Когда parent изменился | 0+ раз | После initState или activate |
| deactivate() | При удалении из tree | 0+ раз | Перед dispose или переиспользованием |
| dispose() | В конце жизни | 1 раз | Финальная очистка |
7. Практическое применение
class _MyWidgetState extends State<MyWidget> {
late StreamSubscription subscription;
@override
void initState() {
super.initState();
// Инициализируем ресурсы один раз
subscription = myStream.listen((event) {
print('Stream event: $event');
});
}
@override
void activate() {
super.activate();
// Если State переиспользуется, можно пересоздать подписку
// или восстановить состояние
print('State переактивирован');
}
@override
void deactivate() {
super.deactivate();
// НЕ закрываем subscription тут!
// Может быть activate() и потребуется она ещё
print('State деактивирован');
}
@override
void dispose() {
// Только тут окончательно очищаем
subscription.cancel();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Container();
}
}
Ключевые моменты
- activate() срабатывает ПОСЛЕ initState при вставке в tree
- activate() может срабатывать НЕСКОЛЬКО РАЗ если State переиспользуется
- deactivate() → activate() — типичная пара при перемещении
- GlobalKey — главная причина вызова deactivate/activate
- В activate() State уже инициализирован, данные сохранены
- dispose() вызывается ОДИН раз в конце жизни, activate НЕ поможет вернуться