情况:父小部件,有两个子部件。
如:
ParentWidget
|-ChildWidgetA
|-ChildWidgetB
ChildWidgetA包含一个数据输入表单,ChildWidgetB包含按钮(保存、取消、导出等)
ChildWidgetB中需要动作(点击按钮)触发ChildWidgetA中的响应(读取和保存文本数据)。
像这样更改父/子关系:
ParentWidget
|-ChildWidgetA
|-ChildWidgetB
...可以工作(所以子可以使用父提供的回调),但在我的实际情况中不可能,除非没有其他可能的解决方案。
我也宁愿不将数据输入表单的知识拉到(不相关的)ParentWidget中,例如,在那里创建TextEditingController
对象以帮助ControlsWidget读取文本值进行保存。
**问题:**如果我改变/重新排列代码,有什么可能性可以让它工作?(可能是流,事件侦听器,状态魔法...?)
下面是一些带注解的示例代码,演示了结构问题:
class ParentWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Column(
children: [
DataEntryFormWidget(), // TextFields with values to read, save
ControlsWidgetWithSaveButton(), // Button I want to trigger the save
],
);
}
}
class DataEntryFormWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Column(
children: [
TextFormField(), // assume I have a way to read values from these
TextFormField(),
// etc
]
);
}
void doSave() {
// read values from TextFormField()
// This is the thing I cannot do from ControlsWidgetWithSaveButton
// because that doesn't have access to TextFormField(s)...
// So can't simply move this code/function to controls widget.
//
// getDatabase.save(... the values ...)
// (all saved ok)
}
}
class ControlsWidgetWithSaveButton extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Row(
children: [
ElevatedButton(
onPressed: () {
// THE PROBLEM:
// Here I want to invoke/trigger the doSave() function.
// Could do the DB write here if I had the data...
},
child: const Text('Save'),
),
// ... <assume some other buttons>
]
);
}
}
1条答案
按热度按时间kqqjbcuj1#
一种方法是使用provider包。同样,你也可以使用其他状态管理包,但这是最简单的一个。
首先,我们需要创建一个
ChangeNotifier
,save
方法将用于通知侦听器请求保存。更改您的
ParentWidget
以注册提供程序您需要将
DataEntryFormWidget
转换为StatefulWidget
,因为我们需要处理initState
和dispose
。在initState
中,我们将添加一个调用doSave
方法的侦听器,在dispose
中,我们将删除侦听器。最后,在
ControlsWidgetWithSaveButton
小部件的onPressed
方法中,我们调用save
来通知侦听器。