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

问题描述

在寻找使用 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(
                ...,));
      }

但比我得到这个错误

enter image description here

我不知道为什么会这样。

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

解决方法

尝试在 Future.deleayd

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

在 Flutter 中,每当需要重新构建小部件时,框架本身都会调用 build 函数。它可以发生很多次!

另一方面,当您想通知用户某事时,您通常希望显示吐司/小吃栏。因此,您可以从 onPressed 和许多其他地方显示小吃栏,但构建功能本身仅用于构建小部件,而不直接响应用户操作。

,

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

这里是 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 "),],),);