Состояние инициализации Flutter вызывается несколько раз

Каждый раз, когда я ухожу от виджета, а затем возвращаюсь к нему, я получаю вызов "n+1" метода initState этого виджета.

У меня установка примерно такая. Я начинаю с виджета A, когда распознан щелчок по карте, мы делаем Navigator.pushNamed(B.routeName), чтобы отобразить экран подробностей для этого элемента. После выполнения дополнительной обработки пользователь нажимает кнопку «Отправить» на B и возвращается к a с помощью Navigator.pushNamed(A.routeName).

class A extends StatefulWidget {

  static String routeName = 'aroutename';
  A({Key key}) : super(key: key);

  _AState createState() => _AState();
}

class _AState extends State<A> {

  @override
  void initState() {
    super.initState();
    getSomeDataForScreenA().then((result) => setState(...));
  }

  whenDone(){

    Navigator.of(context).pushNamed(B.routeName);
  }

  @override
  Widget build(BuildContext context) {
    return Container(

    );
  }
}

class B extends StatefulWidget {
  B({Key key}) : super(key: key);

  _BState createState() => _BState();
}

class _BState extends State<B> {

  static String routeName = 'broutename';

  @override
  void initState() {
    super.initState();
    getSomeDataForScreenB().then((result) => setState(...));
  }

  whenDone(){
    Navigator.of(context).pushNamed(A.routeName);
  }

  @override
  Widget build(BuildContext context) {
    return Container(

    );
  }
}

В первый раз, когда мы видим A, все в порядке, он запускается только один раз. Затем мы идем к B, а затем, как только мы возвращаемся к A, initState() вызывается дважды. В третий раз делаем этот цикл, он вызывается 3 раза и т.д...

Надеюсь, кто-то может указать мне в правильном направлении, что я делаю неправильно. Я знаю, что это, вероятно, связано с непониманием внутренней работы Navigator.of(context), но я нигде не могу найти ответ.

Когда закончите, почему бы просто не использовать Navigator pop?

stuckedoverflow 09.04.2019 05:09
4
1
7 596
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Navigator работает как стек. Он используется для нажатия и выталкивания «маршрута». Виден самый верхний маршрут.

Вот что вы делаете:

  1. Маршрут A добавлен в стек навигатора. Стек: [А]
  2. Маршрут B добавлен в стек навигатора. Стек: [А, В]
  3. Маршрут A добавлен в стек навигатора. Стек: [А, Б, А] ...

Я предполагаю, что поскольку routeName для всех As и B в стеке одинаково, состояние восстанавливается.

Что вы должны сделать, это: Нажмите B, когда закончите, вместо этого снова нажмите A.

whenDone должно выглядеть так:

whenDone(){
 Navigator.of(context).pop(); 
}

Дайте мне знать, если это решит вашу проблему. Если нет, то дайте мне знать, какая у вас проблема с этим.

Harsh Bhikadia 09.04.2019 07:39

Так что я мог бы это сделать, но причина, по которой я выбрал маршрут «push», заключалась в том, что я хотел, чтобы состояние инициализации запускалось снова (не дважды, а только один раз при повторной инициализации), чтобы приложение могло получить самую последнюю версию вещи, которые потенциально были обновлены на Экране B.

schriste92 09.04.2019 17:18

Я понимаю, что это немного расточительно с точки зрения сетевых запросов, но это значительно упрощает логику обеспечения соответствия локального состояния вещей состоянию вещей на стороне сервера.

schriste92 09.04.2019 17:19

В настоящее время я использую шаг VSCode через отладчик, чтобы попытаться определить, почему происходит (n + 1) initState. Я буду обновлять эту тему, если смогу ее найти.

schriste92 09.04.2019 17:20

дайте 'key: UniqueKey' каждому нажатому маршруту, это может решить. это некоторая проблема дублирования состояния.

Harsh Bhikadia 09.04.2019 18:53

если вы посмотрите на мое объяснение выше, вы увидите, что это исправило. Я не уверен, что это ясно. Вы знакомы с плагином flutter_redux?

schriste92 09.04.2019 21:18

понятия не имею о редуксе

Harsh Bhikadia 10.04.2019 00:10

Что бы вы сделали, если бы прошли более одного маршрута, например [A, B, C, [D], A]? Использовать popUntil?

Keith DC 01.07.2021 06:13

@KeithDC popUntil - это то, что я делаю

Harsh Bhikadia 01.07.2021 07:14
Ответ принят как подходящий

Итак, похоже, проблема была в том, как я использовал плагин flutter_redux. Не совсем уверен, что вызвало это, но я полагаю, что это просто принудительное отображение повторяющегося состояния из-за того, как я его использовал.

Короче говоря, я хранил active_tab для BottomTab в состоянии редукции, а не в локальном состоянии для контейнера экрана Home, который у меня был. Причина, по которой я сделал это в первую очередь, заключалась в том, чтобы я мог протолкнуть маршрут на дом, а затем также манипулировать вкладкой, которую он собирался сделать активной в первую очередь.

Я думаю, что просто проведу рефакторинг и использую здесь что-то вроде Флюро, чтобы позволить мне передавать аргументы моим маршрутам, чтобы я мог отображать конкретную вкладку.

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

Другие вопросы по теме