Flutter中如何通过Grandchild组件一键更新Child与Parent变量
问题需求
点击Grandchild组件的按钮,一次性完成以下所有操作:
- 更新Grandchild自身的计数器变量
- 将该变量传递给Child组件
- Child组件用收到的变量计算出新值,再传递给Parent组件更新其显示的数值
要求仅通过这一个按钮完成全部流程,不在Child组件中添加额外按钮。
用户原始代码
Grandchild组件
class GrandChild extends StatefulWidget { Function(int) changeNumber; GrandChild(this.changeNumber, {super.key}); @override State<GrandChild> createState() => _GrandChildState(); } class _GrandChildState extends State<GrandChild> { int counter = 0; @override Widget build(BuildContext context) { return ElevatedButton( onPressed: () { setState(() { ++counter; widget.changeNumber(counter); }); }, child: const Text('Update all')); } }
Child组件
class Child extends StatefulWidget { Function(int) updateParent;//I think this will be needed to update parent Child(this.updateParent, {super.key}); @override State<Child> createState() => _ChildState(); } class _ChildState extends State<Child> { int childCounter = 0; int multiple = 1; int amountInChild = 0; fromGrandChild(int newChildCounter) { setState(() { childCounter = newChildCounter; }); } @override Widget build(BuildContext context) { amountInChild = childCounter * multiple;//this is what I need to update in parent return GrandChild(fromGrandChild); } }
Parent组件
class Parent extends StatelessWidget { Parent({Key? key}) : super(key: key); int amountInParent = 0; receiveFromChild(int newFromChld) { amountInParent = newFromChld; } @override Widget build(BuildContext context) { return Container( child: Column( children: [ Child(receiveFromChild), Text(amountInParent.toString()) ], ), ); } }
解决方法及修改后的代码
核心问题分析
- Parent是StatelessWidget,修改
amountInParent后无法触发UI重建,导致Text不会更新 - Child组件仅在build方法中计算
amountInChild,但没有主动将计算结果传递给Parent,缺少关键的回调触发步骤
修改后的完整代码
Parent组件(改为Stateful)
class Parent extends StatefulWidget { const Parent({Key? key}) : super(key: key); @override State<Parent> createState() => _ParentState(); } class _ParentState extends State<Parent> { int amountInParent = 0; void receiveFromChild(int newFromChild) { setState(() { amountInParent = newFromChild; }); } @override Widget build(BuildContext context) { return Container( child: Column( children: [ Child(receiveFromChild), Text(amountInParent.toString()) ], ), ); } }
Child组件(新增传递逻辑)
class Child extends StatefulWidget { final Function(int) updateParent; const Child(this.updateParent, {super.key}); @override State<Child> createState() => _ChildState(); } class _ChildState extends State<Child> { int childCounter = 0; final int multiple = 1; int amountInChild = 0; void fromGrandChild(int newChildCounter) { setState(() { childCounter = newChildCounter; // 计算完成后直接调用回调传递给Parent amountInChild = childCounter * multiple; widget.updateParent(amountInChild); }); } @override Widget build(BuildContext context) { return GrandChild(fromGrandChild); } }
Grandchild组件(无需修改,优化变量声明)
class GrandChild extends StatefulWidget { final Function(int) changeNumber; const GrandChild(this.changeNumber, {super.key}); @override State<GrandChild> createState() => _GrandChildState(); } class _GrandChildState extends State<GrandChild> { int counter = 0; @override Widget build(BuildContext context) { return ElevatedButton( onPressed: () { setState(() { counter++; widget.changeNumber(counter); }); }, child: const Text('Update all'), ); } }
流程说明
点击Grandchild的按钮后:
- Grandchild内部更新
counter并调用changeNumber回调,将新值传给Child - Child的
fromGrandChild方法触发,更新自身childCounter,同时计算amountInChild并调用updateParent回调传给Parent - Parent收到值后更新
amountInParent并触发UI重建,Text显示最新数值
内容的提问来源于stack exchange,提问作者Ebitu Bonadventure
相关产品推荐
相关产品推荐

