Что такое метод didUpdateWidget в жизненном цикле Flutter?

«Что такое метод didUpdateWidget в жизненном цикле Flutter?» — вопрос из категории Жизненный цикл, который задают на 36% собеседований Flutter Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

didUpdateWidget — это метод жизненного цикла объекта State, который вызывается, когда родительский виджет перестраивается и передает новый экземпляр StatefulWidget с тем же runtimeType и Key. Этот метод позволяет сравнить старый и новый виджеты и при необходимости синхронизировать внутреннее состояние или выполнить побочные эффекты.

Типичный сценарий использования: обновление слушателей или контроллеров при изменении входных параметров виджета.

Пример: Виджет, который подписывается на Stream, идентификатор которого может измениться.

class UserDataWidget extends StatefulWidget {
  final String userId;
  const UserDataWidget({required this.userId, Key? key}) : super(key: key);

  @override
  _UserDataWidgetState createState() => _UserDataWidgetState();
}

class _UserDataWidgetState extends State<UserDataWidget> {
  StreamSubscription? _userDataSubscription;
  UserData? _currentData;

  void _subscribeToUserData(String userId) {
    // Отписываемся от старой подписки
    _userDataSubscription?.cancel();
    // Подписываемся на новый поток данных пользователя
    _userDataSubscription = userRepository.getUserStream(userId).listen((data) {
      setState(() => _currentData = data);
    });
  }

  @override
  void initState() {
    super.initState();
    _subscribeToUserData(widget.userId); // Первоначальная подписка
  }

  @override
  void didUpdateWidget(UserDataWidget oldWidget) {
    super.didUpdateWidget(oldWidget);
    // Если userId изменился, обновляем подписку
    if (oldWidget.userId != widget.userId) {
      _subscribeToUserData(widget.userId);
    }
  }

  @override
  void dispose() {
    _userDataSubscription?.cancel();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Text(_currentData?.name ?? 'Загрузка...');
  }
}

Важно: didUpdateWidget вызывается перед build. В нем можно вызывать setState(). Для первоначальной инициализации используйте initState.