Flutter:当我抛出异常时,构建器在未来的构建器中调用了两次

Posted

技术标签:

【中文标题】Flutter:当我抛出异常时,构建器在未来的构建器中调用了两次【英文标题】:Flutter: Builder calls twice in future builder when i throw exception 【发布时间】:2020-08-14 10:06:48 【问题描述】:

我正在尝试在我未来的构建器上使用小吃栏来显示错误。所以在 initState 方法上创建我未来的方法实例之后:

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 以在构建器上获取错误并显示小吃栏。

我知道未来的构建器是为每个状态显示一个小部件,但我想 显示蛇形条。

但是builder被调用了两次,并且snackbar显示了两次错误? 我在两次 build 中检查了这三个条件是否相同 snapshot.hasError and snapshot.error != null and snapshot.data == null 。如何防止显示两次 snakbar?

【问题讨论】:

如果您只是将print(snapshot); 作为构建器中的第一行,您会在日志上做什么? paste.ubuntu.com/p/y99z2YJ8Rx@pskink 你的有状态小部件也被构建了两次? 这是完整的打印paste.ubuntu.com/p/Jmry3HxWcs@pskink 【参考方案1】:

更新:我分享的代码有问题。请检查一下。

首先,始终在 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'),
                );
              
            ,
          ),
        ),
      ),
    );
  



【讨论】:

以上是关于Flutter:当我抛出异常时,构建器在未来的构建器中调用了两次的主要内容,如果未能解决你的问题,请参考以下文章

当我尝试在调试控制台中构建 APK 以下显示时。构建:构建失败并出现异常

小部件库捕获的异常,在颤振中抛出以下断言构建答案**错误**

如何在codemagic中创建podfile?

Flutter:构建失败并出现异常

Flutter:为啥我的构建器在 Web 服务调用后没有重新加载?

Flutter - 构建失败并出现异常