Flutter自定义Widget调用setState后未刷新问题求助
问题:自定义CartCounter组件点击Reset后无法刷新
我创建了名为CartCounter的自定义Widget,但调用setState后该组件无法刷新。点击Reset按钮想将其值重置为0,但组件没有重建。请问需要对自定义Widget做什么修改,还是存在其他问题?
相关代码
HomeScreen2 代码
class _HomeScreen2State extends State<HomeScreen2> { int english = 0; int maths = 0; @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text( 'English =' + english.toString() + ' Maths=' + maths.toString()), ), body: Column( children: [ CartCounter( value: english, onChange: (value) { setState(() { english = value; }); }), CartCounter( value: maths, onChange: (value) { setState(() { maths = value; }); }), ElevatedButton( onPressed: () { setState(() { english = 0; maths = 0; }); }, child: Text('Reset'), ), ], ), ); } }
CartCounter 组件代码
class CartCounter extends StatefulWidget { final int value; final Function(int) onChange; const CartCounter({Key? key,required this.value,required this.onChange}) : super(key: key); @override State<CartCounter> createState() => _CartCounterState(); } class _CartCounterState extends State<CartCounter> { late int result; @override void initState() { super.initState(); result=widget.value; } @override Widget build(BuildContext context) { return Container( height: 80, width: 200, decoration: BoxDecoration( borderRadius: BorderRadius.circular(20) ), child: Row( mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ IconButton( color: Colors.blue, onPressed: (){ setState(() { result--; widget.onChange(result); }); }, icon: Icon(Icons.remove)), SizedBox(width: 60,child: Center(child: Text(result.toString(),style: Theme.of(context).textTheme.headlineSmall,)),), IconButton( color: Colors.blue, onPressed: (){ setState(() { result++; widget.onChange(result); }); }, icon: Icon(Icons.add)), ],), ); } }
问题原因
CartCounter的内部状态result仅在initState中初始化了一次,而initState只会在组件首次创建时执行。当点击Reset按钮后,父组件的english和maths被重置为0,CartCounter的widget.value也随之更新,但组件内部的result并没有同步这个新值,因此组件不会触发重建,界面也就不会刷新。
解决方案
在_CartCounterState中重写didUpdateWidget方法,当父组件传递的value发生变化时,同步更新内部的result状态并触发重建:
class _CartCounterState extends State<CartCounter> { late int result; @override void initState() { super.initState(); result = widget.value; } // 添加这个方法 @override void didUpdateWidget(covariant CartCounter oldWidget) { super.didUpdateWidget(oldWidget); // 当widget.value和旧值不同时,更新result if (oldWidget.value != widget.value) { setState(() { result = widget.value; }); } } @override Widget build(BuildContext context) { // 原build代码不变 return Container( height: 80, width: 200, decoration: BoxDecoration( borderRadius: BorderRadius.circular(20) ), child: Row( mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ IconButton( color: Colors.blue, onPressed: (){ setState(() { result--; widget.onChange(result); }); }, icon: Icon(Icons.remove)), SizedBox(width: 60,child: Center(child: Text(result.toString(),style: Theme.of(context).textTheme.headlineSmall,)),), IconButton( color: Colors.blue, onPressed: (){ setState(() { result++; widget.onChange(result); }); }, icon: Icon(Icons.add)), ],), ); } }
这样修改后,当父组件的english或maths变化时,CartCounter会检测到widget.value的更新,同步内部状态并刷新界面,点击Reset按钮后就能正常重置数值了。
内容的提问来源于stack exchange,提问作者user22362195
相关产品推荐
相关产品推荐

