Flutter 颤振:当我抛出异常时,生成器在未来的生成器中调用两次

Flutter 颤振:当我抛出异常时,生成器在未来的生成器中调用两次,flutter,flutter-layout,future,Flutter,Flutter Layout,Future,我试图在future builder上使用snackbar显示错误。因此,在initState方法上创建future方法实例后: Future<DetailModel> futureDetail; ... @override void initState() { futureDetail = DetailProvider().detailProvider(widget.id); super.initState(); } 在futur

我试图在future builder上使用snackbar显示错误。因此,在initState方法上创建future方法实例后:

Future<DetailModel> futureDetail;
  ...
   @override
  void initState() {
    futureDetail =
        DetailProvider().detailProvider(widget.id);
    super.initState();
  }
在futureBuilder中,我使用如下:

Center(
              child: SingleChildScrollView(
                child: FutureBuilder(
                  future: futureDetail,
                  builder:
                      (context, AsyncSnapshot<DetailProductModel> snapshot) {
                    if (!snapshot.hasError ||
                        snapshot.connectionState == ConnectionState.waiting) {
                      return Center(
                        child: CircularProgressIndicator(),
                      );
                    }
                    if (snapshot.hasData && snapshot.data.data != null) {
                      return Container();
                    }
                    if (snapshot.hasError &&
                        snapshot.error != null &&
                        snapshot.data == null) {
                      WidgetsBinding.instance.addPostFrameCallback((_) =>
                          showSnackbar(snapshot.error.toString(), context));
                      return Container();
                    } else {
                      return Center(
                        child: Text('failed to load'),
                      );
                    }
                  },
                ),
              ),
            ),
detailProvider方法调用http服务,在我的示例中,我抛出SocketException以获取生成器上的错误并显示snackbar

我知道future builder是用于显示每个状态的小部件,但我想 展示蛇吧

但是生成器被调用了两次,snackbar显示了两次错误? 我检查了这三个条件是否相同snapshot.hasError和snapshot.error!=两次生成中的null和snapshot.data==null。我怎样才能避免显示两次snakbar?

更新:我共享的代码有问题。请看这个

首先,始终在FutureBuilder之外创建SnackBar,因为FutureBuilder经常被调用,因此它会导致无限循环。您可以做的是使用catchError。在使用我们已经声明的变量创建新的SnackBar之前,您仍然可以检查是否存在活动SnackBar

您将看到SnackBar只显示一次,即使在您运行下面的代码时我调用了三次

应用相同的方法更新您自己的代码:

class App extends StatefulWidget {
  @override
  _AppState createState() => _AppState();
}

class _AppState extends State<App> {
  bool snackBarActive = false;
  Future<String> futureDetail;

  @override
  void initState() {
    futureDetail = Future<String>.error('An error Occurred').catchError((errText) {
      showSnackBar(errText);
      showSnackBar(errText);
      showSnackBar(errText);
    });
    super.initState();
  }

  void showSnackBar(String errText) {
    if (!snackBarActive) {
      setState(() {
        snackBarActive = true;
      });

      WidgetsBinding.instance.addPostFrameCallback((_) => Scaffold.of(context)
              .showSnackBar(SnackBar(
                content: Text(errText),
              ))
              .closed
              .whenComplete(() {
            setState(() {
              snackBarActive = false;
            });
          }));
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: SingleChildScrollView(
          child: FutureBuilder(
            future: futureDetail,
            builder: (context, AsyncSnapshot<String> snapshot) {
              if (!snapshot.hasError &&
                  snapshot.hasData &&
                  snapshot.data != null) {
                return Container();
              } else {
                return Center(
                  child: Text('failed to load'),
                );
              }
            },
          ),
        ),
      ),
    );
  }
}



如果您只是打印快照,那么您在日志上看到了什么;作为构建器中的第一行@pskink和您的有状态小部件也构建了两次?这是全文@pskink