来自 FutureBuilder 的 Navigator.pop

Posted

技术标签:

【中文标题】来自 FutureBuilder 的 Navigator.pop【英文标题】:Navigator.pop from a FutureBuilder 【发布时间】:2020-07-11 00:47:51 【问题描述】:

我有一个要求用户输入的第一个屏幕,然后当用户单击一个按钮时,应用程序会进入第二个屏幕,该屏幕使用 FutureBuilder 调用 API。

如果 API 返回错误,我想使用 Navigator.pop 返回上一个屏幕。当我尝试在 FutureBuilder 的构建器中执行此操作时,我收到一个错误,因为我在构建树时修改了它...

setState() 或 markNeedsBuild() 在构建期间调用。这个覆盖 无法将小部件标记为需要构建,因为框架是 已经在构建小部件的过程中

如果发生错误,转到上一个屏幕的正确方法是什么?

class *** extends StatelessWidget 

  @override
  Widget build(BuildContext context) 
    return Scaffold(
      body: Center(
          child: FutureBuilder<Flight>(
            future: fetchData(context),
            builder: (context, snapshot) 
              if (snapshot.hasData) 
                return ScreenBody(snapshot.data);
               else if (snapshot.hasError) 
                Navigator.pop(context, "an error");
              
              // By default, show a loading spinner.
              return CircularProgressIndicator();
            ,
          )
      ),
    );
  

PS:我尝试使用 addPostFrameCallback 并使用里面的 Navigator.pop,但由于某些未知原因,它被多次调用

【问题讨论】:

请分享您的代码???? 也发布错误。 错误是什么? 你能确认它在这条线上崩溃了吗? Navigator.pop(context, "an error"); 是的。我确认它在这条线上崩溃了。 【参考方案1】:

构建方法运行时不能直接导航,所以最好显示一些错误屏幕并给使用机会返回上一个屏幕。

但是,如果您想这样做,那么您可以使用以下语句来这样做。

Future.microtask(() => Navigator.pop(context));

【讨论】:

它似乎工作,但它被多次调用,所以它至少弹出两次...... 多次调用是什么意思,实际发生了什么? 屏幕变黑。当我用调试器检查时,Future.microtask 被调用了两次,所以 Navigator.pop 也被调用了两次。我不知道为什么,但这就是发生的事情。但是,构建函数被多次调用似乎并不令人难以置信。 你是如何学习这些东西的? “构建方法运行时无法直接导航”?我不知道,而且似乎没有充分的理由。 屏幕构建时无法导航或调用setState,所以你必须这样做,或者你可以使用future等待微秒然后进行导航。【参考方案2】:

我更愿意将 class 转换为 StateFullWidget 并摆脱 FutureBuilder

class *** extends StatefulWidget 

  @override
  _***State createState() => _***State();


class _***State extends State<***> 
  Flight flight;

  @override
  void initState() 
    super.initState();
    fetchData().then((data) 
      setState(() 
        flight = data;
      );
    ).catchError((e) 
      Navigator.pop(context, "an error");
    );
  

  @override
  Widget build(BuildContext context) 
    return Scaffold(
      body: Center(
        child: flight != null ? ScreenBody(flight) : CircularProgressIndicator(),
      ),
    );
  

当然通过context在课外某处不是好方法

【讨论】:

以上是关于来自 FutureBuilder 的 Navigator.pop的主要内容,如果未能解决你的问题,请参考以下文章

FutureBuilder 与 Notifylistener 冲突

如何在 FutureBuilder 中解析从本地主机接收的 JSON 对象

Flutter FutureBuilder 小部件动态列表长度

带有 Firebase 实时数据库和 futurebuilder 的 Gridview.builder

如何使用 Future Builder 创建包含来自 Cloud FireStore 的数据的列表

FlutterFuture 与 FutureBuilder 异步编程代码示例 ( FutureBuilder 构造函数设置 | 处理 Flutter 中文乱码 | 完整代码示例 )