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

#asynchronous #flutter #future

#асинхронный #флаттер #будущее

Вопрос:

Чтобы меня не FutureBuilder вызывали снова и снова (см. Это), у меня есть привычка вызывать мои futures, initState и это всегда работало нормально, пока мне не пришлось использовать вложенные.

По сути, я хочу, чтобы второе будущее вызывалось только после connectionState того, как станет 1 done -м. Любая помощь?

Вот мой код для дальнейшего объяснения-

 FutureBuilder(
  future: _future1,
  builder: (BuildContext context, AsyncSnapshot snapshot) {
    return snapshot.connectionState != ConnectionState.done
        ? CircularProgressIndicator()
        : snapshot.data != 200
            ? SomeWidget()
            : FutureBuilder(
                future: _future2,
                builder: (BuildContext context, AsyncSnapshot snapshot) {
                  return snapshot?.connectionState == ConnectionState.done
                      ? Text('')
                      : CircularProgressIndicator();
                });
  },
);
  

Итак, в принципе, я вообще не хочу, _future2 чтобы меня вызывали, если данные, полученные от _future1 , не равны 200. Другими словами, я хочу решить _future2 , следует ли вызывать или нет на основе результата _future1 .

Комментарии:

1. не могли бы вы подробнее рассказать. используете ли вы AsyncMemoizer , как описано в ссылке? добавление некоторого кода помогло бы.

2. Я добавил код, чтобы объяснить больше, и нет, я не использую AsyncMemoizer . Должен ли я это делать?

3. просто используйте one FutureBuilder — вам не нужны эти два вложенных FutureBuilder s — вместо этого вы должны использовать a Future , который завершается на основе ваших двух других Future s

4. Я вас не понял. Не могли бы вы объяснить подробнее? (Если возможно, с помощью кода.)

5. вам не нужно Future.wait , вам нужно expensiveA() .then((aValue) => expensiveB()) .then((bValue) => expensiveC()) .then((cValue) => doSomethingWith(cValue)); или что-то в этом роде, подробнее здесь или здесь

Ответ №1:

В initState , я делаю это —

 _future1 = func.then(checkCode);
  

А затем я написал другую функцию для определения моего виджета в зависимости от кода, который я получаю —

 checkCode(int statusCode) {
if (statusCode == 200) {
  _future2Func();
  widgetToNavigate = Text('');
} else {
  widgetToNavigate = SomeWidget();
}}
  

Итак, наконец, мой код сборки выглядит так —

 Widget build(BuildContext context) {
return FutureBuilder(
  future: _future1,
  builder: (BuildContext context, AsyncSnapshot snapshot) {
    return snapshot.connectionState != ConnectionState.done
        ? CircularProgressIndicator()
        : widgetToNavigate;
  },
);}
  

Комментарии:

1. вы все еще используете два FutureBuilder s … — один in checkCode() и другой in build() метод

2. Только если я получу 200 в первом. Мне нужно загрузить информацию и показать индикатор выполнения, пока информация не будет загружена… Это неправильно?

3. используйте один FutureBuilder внутренний build() метод, который либо создает CircularProgressIndicator , либо YourFinalWidget когда ваш Future завершается

4. здесь вы можете прочитать, как бороться с ошибками с FutureBuilder помощью — я имею в виду: if (snapshot.hasError) { ...