ScaffoldMessenger.of(context).showSnackBar() 在小部件构建函数中直接调用时不起作用

ScaffoldMessenger.of(context).showSnackBar() doesn't work when called directly inside a widget build function

在寻找使用 flutter SnackBarScaffoldMessenger 的示例时,我只找到了 onPressed 函数的用法:

    Widget build(BuildContext context) {
        return Container(
            child: ElevatedButton(
              child: ...,
              onPressed: () => _showToast(context),
            ));
      }
    
      void _showToast(BuildContext context) {
        final scaffold = ScaffoldMessenger.of(context);
        scaffold.showSnackBar(
          SnackBar(content: const Text('Added to favorite')),
        );
      }
    }

但是没有一个例子解释了为什么必须只将它与 onPressed 一起使用, 所以我自己尝试并直接在构建函数中使用:

         Widget build(BuildContext context) {
           _showToast(context);   <---
           return Container(
              child: ElevatedButton(
                ...,
            ));
      }

但是我得到了这个错误:

我不确定为什么会这样。

我最终给了 Scaffold 一个密钥并使用了 GlobalKey<ScaffoldState> 方法,但我真的很想了解为什么使用 ScaffoldMessenger.of(context).showSnackBar() 没有 callback\onPressed 不起作用

尝试在 Future.deleayd

中添加或声明您的小吃店
Future.delayed(Duration.zero, () async {
                  yourSnackBarFunction();
                });

在 Flutter 中 build 函数在需要重建小部件时由框架本身调用。它可以出现很多次!

另一方面,当您想要通知用户某事时,通常需要显示吐司/小吃店。所以你可以从 onPressed 和许多其他地方显示一个 snackbar,但是构建函数本身只是为了构建一个小部件,而不是直接响应用户操作。

ScaffoldMessenger.of(context) 我们需要给一些时间来正确渲染(对于完整的脚手架)。我们可以知道从addPostFrameCallback开始的时间。此外,如果您尝试显示小部件的中间部分,第一部分将呈现,但其余小部件将面临此问题。

这里是 build 方法的解决方案。

  WidgetsBinding.instance!.addPostFrameCallback((timeStamp) {
      _showToast(context);
    });

为了正确理解这个概念,我们可以做这样的事情。

Scaffold(
      body: Container(
        height: 100,
        color: Colors.cyanAccent,
        child: Column(
          children: [
            Text("This text will render "),
            Builder(builder: (context) {
              _showToast(context);

              ///but you will be able to see Message
              return Text("it will cause error");
            }),
            Text("This text will not render "),
          ],
        ),
      ),
    );