Flutter中Dialog内调用setState无法更新父组件状态如何解决?
问题根源
你代码里的currentTheme变量定义在build方法内部,属于局部变量。每次父组件调用setState触发重绘时,build方法都会重新执行,currentTheme会被强制重置为WrittenTextTheme.light,所以看起来像是父组件状态没有更新。
解决步骤
1. 基础修复
将currentTheme从build方法中提升为WritingScreenState类的成员变量,作为全局状态存储即可:
class WritingScreenState extends State<WritingScreen> { late List<Section> sections; // 移到类作用域下作为成员变量,不要放在build方法内 WrittenTextTheme currentTheme = WrittenTextTheme.light; @override void initState() { super.initState(); sections = []; } @override Widget build(BuildContext context) { // 移除原来这里的currentTheme定义 return Scaffold( // 原有代码不变 ); } }
改完之后你原有逻辑里调用父组件setState更新currentTheme就可以正常生效了。
2. 优化方案(推荐)
目前你选中主题就直接修改全局状态,如果用户点击取消关闭Dialog,已经修改的状态无法回滚,体验不佳。可以在Dialog内用临时变量存储选中值,用户确认保存后再同步到父组件:
IconButton( icon: Icon(Icons.tune), tooltip: "Preferences", onPressed: () { showDialog(context: context, builder: (context) { // Dialog内临时存储选中的主题,初始值等于当前全局主题 WrittenTextTheme selectedTheme = currentTheme; return AlertDialog( title: Text("Preferences"), content: StatefulBuilder( builder: (context, StateSetter updateDialogState) { return Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ Text("Theme"), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Flexible( flex: 1, child: InkWell( onTap: () { // 仅更新Dialog内部的临时状态 updateDialogState(() { selectedTheme = WrittenTextTheme.light; }); }, child: Container( height: 50, decoration: BoxDecoration( color: Colors.white, border: selectedTheme == WrittenTextTheme.light ? Border.all(color: Theme.of(context).primaryColor, width: 3) : Border.all(), borderRadius: BorderRadius.circular(6) ), child: Align( alignment: Alignment.center, child: Text( "Aa", style: TextStyle( fontSize: 28, color: Colors.grey[800], ) ), ), ), ), ), Flexible( flex: 1, child: InkWell( onTap: () { updateDialogState(() { selectedTheme = WrittenTextTheme.dark; }); }, child: Container( height: 50, decoration: BoxDecoration( color: Colors.blueGrey[800], border: selectedTheme == WrittenTextTheme.dark ? Border.all(color: Theme.of(context).primaryColor, width: 3) : Border.all(), borderRadius: BorderRadius.circular(6) ), child: Align( alignment: Alignment.center, child: Text( "Aa", style: TextStyle( fontSize: 28, color: Colors.grey[100], ) ), ), ), ), ), ] ), ], ); } ), actions: [ TextButton( child: Text("取消"), onPressed: () => Navigator.pop(context), ), ElevatedButton( child: Text("SAVE"), onPressed: () { // 点击保存时再同步到父组件全局状态 setState(() { currentTheme = selectedTheme; }); Navigator.pop(context); }, ) ], ); }); } )
内容的提问来源于stack exchange,提问作者simeondermaats
相关产品推荐
相关产品推荐

