美文网首页编程二三事
在Flutter中使用SetState无效?可能是忽略了这个!

在Flutter中使用SetState无效?可能是忽略了这个!

作者: 萧文翰 | 来源:发表于2020-06-20 10:45 被阅读0次

    这次是Flutter开发技术分享,解决的问题点来自本人实际的开发经历。
    首先描述一下问题:在某个组件中调用setState()方法更新该组件状态,结果是无法做到更新效果,组件仍然维持原状。
    下面我们用代码示例还原问题场景:

    class _MyHomePageState extends State<MyHomePage> {
      bool isChecked = false;
    
      showTestDialog() {
        showDialog(
          context: context,
          builder: (BuildContext context) {
            return SimpleDialog(title: Text("测试对话框标题"), children: <Widget>[
              Row(children: <Widget>[
                Checkbox(
                    value: this.isChecked,
                    onChanged: (bool val) {
                      setState(() {
                        this.isChecked = !this.isChecked;
                      });
                      debugPrint(this.isChecked.toString());
                    }),
                Text("测试复选框")
              ])
            ]);
          },
        );
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: Text(widget.title),
          ),
          body: Center(
              child: RaisedButton(
            child: Text("点击出现弹窗"),
            onPressed: () {
              showTestDialog();
            },
          )),
        );
      }
    }
    

    为了突出问题点,减少不必要的干扰,我简化了原有代码内容。通过阅读上述代码,我们得知整个Demo的界面有一个按钮构成,当按钮被点击时,showTestDialog()方法被执行。界面将显示一个小窗口,里面有一个复选框。
    我们要实现的效果当然是用户点击复选框的时候,改变复选框的状态。因此,在复选框的onChanged()方法中改变了决定复选框状态的布尔值,并setState()。
    然而真实的运行结果并非像预期那样产生效果。
    究其原因,我们还需从setState()说起。
    顾名思义,setState()要求其作用对象必须是一个有状态的组件。如果作用对象本身无状态,那么setState()将无法起作用。
    因此,我们找到原因:SimpleDialog()中的子组件默认是无状态的。
    接下来的解决办法就简单了,只需要在SimpleDialog组件外部“套”一个StatefulBuilder组件即可。参考下面的代码:

    class _MyHomePageState extends State<MyHomePage> {
      bool isChecked = false;
    
      showTestDialog() {
        showDialog(
          context: context,
          builder: (BuildContext context) {
            return StatefulBuilder(
              builder:
                  (BuildContext context, void Function(void Function()) setState) {
                return SimpleDialog(title: Text("测试对话框标题"), children: <Widget>[
                  Row(children: <Widget>[
                    Checkbox(
                        value: this.isChecked,
                        onChanged: (bool val) {
                          setState(() {
                            this.isChecked = !this.isChecked;
                          });
                          debugPrint(this.isChecked.toString());
                        }),
                    Text("测试复选框")
                  ])
                ]);
              },
            );
          },
        );
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: Text(widget.title),
          ),
          body: Center(
              child: RaisedButton(
            child: Text("点击出现弹窗"),
            onPressed: () {
              showTestDialog();
            },
          )),
        );
      }
    }
    

    再次运行,对话框中的复选框可以正常响应。至此,问题解决。

    相关文章

      网友评论

        本文标题:在Flutter中使用SetState无效?可能是忽略了这个!

        本文链接:https://www.haomeiwen.com/subject/tuswxktx.html