← Назад к вопросам

Что такое 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();
  }
}
Что такое initState(), didChangeDependencies() и dispose()? | PrepBro