Будущее работает дважды, потому что это в методе сборки, как это исправить? - PullRequest
2 голосов
/ 05 ноября 2019

Скажем, у меня есть функция, которая создает какой-то большой файл

Future<File> makeBigFile() async {
    // lots of processing
    return File("generated_file.txt");
}

@override
Widget build(BuildContext context) {
  return FutureBuilder(
    future: makeBigFile(),
    builder: (BuildContext context, AsyncSnapshot snapshot) {
      if (snapshot.hasData && snapshot.data is File) {
        return Text("Success!");
      } else if (snapshot.connectionState==ConnectionState.done) {
        return Text("Error!");
      } else {
        return CircularProgressIndicator();
      }
    }
  );
}

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

Будущее должно быть получено раньше, например, во время State.initState, State.didUpdateConfig или State.didChangeDependencies. Его нельзя создавать во время вызова метода State.build или StatelessWidget.build при создании FutureBuilder. Если будущее создается одновременно с FutureBuilder, то каждый раз, когда родитель FutureBuilder перестраивается, асинхронная задача перезапускается.

Из того, что я понимаю (что не так много, несмотря на то, чточтение и перечитывание документов) FutureBuilder должен быть в build() и должен иметь future:, который может запускаться несколько раз без проблем, но что, если это какая-то длинная операция, которая не должна запускаться несколько раз?

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

Ответы [ 2 ]

2 голосов
/ 05 ноября 2019
class BigFileWidget extends StatefulWidget {
  @override
  _BigFileWidgetState createState() => _BigFileWidgetState();
}

class _BigFileWidgetState extends State<BigFileWidget> {

  Future<File> fileFuture;

  @override
  void initState() {
    fileFuture = makeBigFile();
  };

  Future<File> makeBigFile() async {
    // lots of processing
    return File("generated_file.txt");
  }

  @override
  Widget build(BuildContext context) {
    return FutureBuilder(
        future: fileFuture,
        builder: (BuildContext context, AsyncSnapshot snapshot) {
          if (snapshot.hasData && snapshot.data is File) {
            return Text("Success!");
          } else if (snapshot.connectionState==ConnectionState.done) {
            return Text("Error!");
          } else {
            return CircularProgressIndicator();
          }
        }
    );
  }
}
1 голос
/ 05 ноября 2019
File myFile;
bool isLoading = false;

Future<File> makeBigFile() async {
    isLoading = true;
    // lots of processing with await methods
    myFile = File("generated_file.txt");
    setState({
        isLoading = false;
    });
}

@override
void initState() {
    makeBigFile();
};

@override
Widget build(BuildContext context) {
    return isLoading 
        ? CircularProgressIndicator()
        : Text( myFile == null ? "Error" : "Success");
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...