Руководство по использованию методов жизненного цикла виджетов для эффективной разработки Flutter.

В общих чертах жизненный цикл представляет собой этап от его создания до его уничтожения. В контексте флаттера - то же самое. Сегодня мы обсудим жизненный цикл виджета (не путайте с жизненным циклом приложения).

То, как мы, разработчики флаттера, должны использовать эти методы жизненного цикла, является основной целью этой статьи, поэтому давайте перейдем к интересной части.

создать состояние()

Когда мы создаем виджет с состоянием во Flutter, немедленно вызывается метод createState для возврата экземпляра состояния связанного класса.

Это важно, потому что во Flutter все неизменяемо (включая виджеты с отслеживанием состояния). Важно отделить задачу изменяемости и делегировать ее классу состояния. Таким образом, Flutter может заставить неизменяемые классы выглядеть и работать как изменяемые, и мы можем видеть все изменения в пользовательском интерфейсе.

Это также имеет преимущество в производительности, поскольку Flutter проще изменить переменную состояния и отразить изменение оптимизированным образом, чем воссоздавать все дерево виджетов из-за небольших изменений.

class HomePage extends StatefulWidget {
  @override
  _HomePageState createState() => new _HomePageState();
}

состояние инициализации()

Это первый метод, называемый созданием после состояния. И он вызывается только один раз.
Этот метод можно использовать для:

  1. Инициализировать поздние переменные
  2. Подпишись на стрим и тд.
@override
initState() {
  super.initState();
  _controller=TextEditingController();
  myStream.listen((data) {});
}

didChangeDependencies

Этот метод вызывается сразу после initState() в первый раз и позже при изменении его зависимости.

Итак, в чем именно заключается его зависимость?
Допустим, мы используем MediaQuery.of в виджете, тогда мы можем сказать, что наш виджет зависит в MediaQuery. Поэтому всякий раз, когда MediaQuery обновляет данные, этот метод срабатывает.

Таким образом, мы можем сказать, зависит ли наш виджет от Inherited Widget (медиа-запрос, тема, поставщики и т. д.), и всякий раз, когда эти унаследованные виджеты отправляют обновления, он запускает этот метод.

После того, как этот метод build() будет запущен, поэтому у разработчика не так много сценариев, в которых нам, возможно, придется использовать здесь пользовательскую логику, но согласно официальной документации это говорит

выполнять какую-то дорогостоящую работу (например, выборку по сети) при изменении их зависимостей, и эта работа будет слишком дорогой для каждой сборки.

Например: из вашего Inherited Widget вы можете получить какое-то значение, и вам нужно будет выполнить какую-то дорогостоящую операцию на основе этого значения и показать его в пользовательском интерфейсе. Возможно, вы не захотите делать это в методе сборки, поэтому didChangeDependencies будет идеальным местом для этого.

сделалUpdateWidget

Давайте возьмем пример, чтобы понять это. У вас есть Container красного цвета, и нажатием кнопки вы меняете его на синий.

Здесь и старый, и новый экземпляры объекта имеют один и тот же тип runtimeType , но данные разные, поэтому в этом случае срабатывает этот метод. Он также получает старые виджеты didUpdateWidget(Widget oldWidget) .

@override
void didUpdateWidget(Widget oldWidget) {
  if (oldWidget.color != widget.color) {
  /// Your logic
  }
}

Как мы можем это использовать?

  • Один из возможных сценариев можно использовать в анимации для перехода между значениями.
  • Другим может быть конкретный вариант использования, основанный на требованиях вашего приложения, на основе нового значения виджета, выполняющего некоторые другие задачи, например: подписаться на новый поток и отказаться от подписки на более ранний поток.

Так как метод build() будет вызываться после этого метода, то вызов setState((){}) в этом методе является излишним.

строить()

Это важный метод, когда нам как программисту нужно вернуть виджет, который мы хотим показать пользователю.

Кроме того, этот метод может запускаться несколько раз, поэтому не рекомендуется выполнять дорогостоящие задачи внутри этого метода.

Этот метод потенциально может вызываться в каждом кадре и не должен иметь никаких побочных эффектов, кроме создания виджета.

установить состояние (() {})

setState((){}) — это метод, который принимает метод в качестве параметра и внутренне вызывает метод markNeedsBuild() для запуска новой сборки.

/// Implementation of setState() in flutter 
@protected
void setState(VoidCallback fn) {
  final Object? result = fn() as dynamic;
  _element!.markNeedsBuild();
}

Здесь мы можем увидеть внутреннюю реализацию setState. Сначала он запускает переданный нами метод и запускает markNeedsBuild() . Из этого кода реализации мы можем вывести еще одну вещь, которая

  • мы не должны передавать асинхронную функцию в setState, поскольку внутренне она не будет ждать разрешения будущего, поэтому мы не увидим желаемого отражения пользовательского интерфейса.

Таким образом, как разработчик, мы можем использовать этот метод, чтобы уведомить Flutter о том, что что-то изменилось, и обновить пользовательский интерфейс.

setState(() {
  /// New State values
  color=Colors.red;
});

распоряжаться ()

Метод dispose() вызывается при удалении объекта состояния. Это последний метод, который запускается в жизненном цикле.

Итак, как разработчик, мы можем:

  1. Отписаться от стримов
  2. Утилизируйте контроллеры
  3. Остановить анимацию и т. д.

Итак, это самые распространенные и обязательные для понимания методы жизненного цикла во Flutter.

Поскольку виджет без сохранения состояния не имеет собственного изменяемого состояния (очевидно из названия), здесь отсутствуют некоторые методы жизненного цикла, например initState , dispose и т. д.

Источники:
https://www.youtube.com/watch?v=_gIbneld-bw
https://api.flutter.dev/index.html