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

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

class _MyHomePageState extends State { bool isChecked = false; showTestDialog() { showDialog( context: context, builder: (BuildContext context) { return SimpleDialog(title: Text("测试对话框标题"), children: [ Row(children: [ 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 { 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: [ Row(children: [ 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(); }, )), ); } }

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

    推荐阅读