【问题标题】:setState() or markNeedsBuild() called when widget tree was locked小部件树被锁定时调用 setState() 或 markNeedsBuild()
【发布时间】:2021-09-16 18:49:32
【问题描述】:

颤动

我正在尝试将一个小部件显示到 Stack IF an condition (true or false ) 中,它可以正常工作 但是当我需要将条件 bool 更改为 SetState 以再次隐藏小部件时,它也可以工作,但会出现烦人的错误消息,即 setState() or markNeedsBuild() called when widget tree was locked

我的代码很复杂,但我将展示一个简单的类似示例

bool displayWidget = false;
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(),
      body: Stack(
        children: [
          Container(
            child: TextButton(
              onPressed: () {
                final result = await FilePicker.platform.pickFiles(allowMultiple: false );
                if (result == null) return;
                final path = result.files.single.path;
                setState(() => displayWidget = true);
              },
            child: Text ("studio")
            ),
          ),
          displayWidget?
          GestureDetector(
            onTap: ()=> setState(() => displayWidget = false), // the  error happen when i click here 
            child: Container(
              child:  Image.asset("here is the picture in full secreen"),
            ),
          ):Container()
        ],
      ),
    );
  }
}

我知道有比这种方式更好的照片查看器 :D 但我只为其他真实案例举一个简单的例子

【问题讨论】:

    标签: flutter dart widget setstate


    【解决方案1】:

    我从flutter官网找到解决办法

    简单地将集合状态包装成

    这种解决方案适用于大多数情况

          if(!mounted) {
             setState
            
               }
    or  
    
    if(mounted) { // depends on your widget case
     setState
         }
    

    来源https://www.kindacode.com/article/flutter-error-setstate-called-after-dispose/

    如果没有,试试这个

    WidgetsBinding.instance
        .addPostFrameCallback((_) => setState(() {}));
    

    来源https://www.thetopsites.net/article/50288698.shtml

    我在 stackoverflow 中发现许多答案的相同错误 按下面

    Flutter setState() or markNeedsBuild() called when widget tree was locked

    【讨论】:

    • 能否请您指出在flutter官方网站上建议这样做的地方?这是一个简单的状态管理问题,setState 不需要对其进行任何添加即可按预期工作。
    • 检查 mounted 是否确实比 Timer 更好的方法(您在编辑之前在此答案中建议)但在大多数情况下它仍然是多余的。另外,您实际上提供的所有资源都不是来自 Flutter 官方文档。某些建议所提供的并不总是最佳实践。有时答案和文章作者缺乏对状态管理和小部件生命周期的理解。我强烈建议对此进行更深入的研究。
    • 老实说,我错过了我找到文档的网站,请解释我想帮助的问题
    【解决方案2】:

    请看看这个例子是否对你有帮助(我稍微简化了你的例子,以便它可以在 dartpad 中轻松运行)。 在您的情况下,onPressed 函数应包含您的文件选择逻辑并具有您期望的返回类型(可能是String?)并检查返回值是否不为空,然后显示您的图像

    class MyWidget extends StatefulWidget {  
      @override
      State<MyWidget> createState() => MyWidgetState();
    }
    
    class MyWidgetState extends State<MyWidget> {
      
      bool displayWidget = false;
      
      bool onPressed(bool isShown) {
        //instead of this mocked function pickFile here 
        return !isShown;
      }
      
        @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(),
          body: Row(
            children: [
              Container(
                child: TextButton(
                  onPressed: () {
                    displayWidget = onPressed(displayWidget);
                    setState(() => displayWidget);
                  },
                child: Text ("Show or hide text"),
                ),
              ),
              if(displayWidget)
              GestureDetector(
                onTap: ()=> setState(() => displayWidget = !displayWidget),
                child: Container(
                  child:  Text('This text is to be shown'),
                ),
              ),
            ],
          ),
        );
      }
    }
    

    【讨论】:

    • 非常感谢您的帮助,但请看下面的答案,我找到了解决方案
    【解决方案3】:

    首先我想问你@override 在哪里?您是否忘记在问题中添加该内容?如果是,那么该错误可能与此有关。如果不是,请尝试在@override 上方声明布尔值。

    【讨论】:

    • 缺少@override 注解不会以任何方式影响您的代码,也不会导致任何编译或运行时错误。
    • 缺少覆盖注释根本没有影响,基本上@override 对函数而不是变量有意义,但我找到了解决方案并将其作为答案发布,所以每个人都会从中受益,但无论如何都要感谢
    猜你喜欢
    • 2018-01-06
    • 1970-01-01
    • 1970-01-01
    • 2021-02-03
    • 2022-08-22
    • 2023-02-14
    • 2020-10-05
    • 2018-05-15
    • 2020-12-12
    相关资源
    最近更新 更多