问题描述
我将数据从父级传递给子级,其中一个参数是 Fn。我需要的是再次将数据从孩子返回给父母,但我收到如下错误:
[ 参数不匹配的闭包调用:函数 '_ReservationBranchesSlotsScreenState._changeData' 接收器:闭包: ({String areaId,int CoastPerPerson,int selectedBranchChecked,String 格式化,bool showCreateReservationButton,bool isExpanded,int expandindex}) => 来自函数“_changeData@176179245”的无效:。试过 调用:_ReservationBranchesSlotsScreenState._changeData(areaId: "d98a4e0e-d408-40c8-b387-9a405683a389",CoastPerPerson: 0,Expandedindex: -1,格式化: null,isExpanded: false,selectedBrnachChecked: 0,showCreateReservationButton: false) 找到: _ReservationBranchesSlotsScreenState._changeData({String areaId,String formatted,bool showCreateReservationButton,int Expandedindex}) => 无效]
我在父控件中创建了一个函数来执行一些操作,并将这个 Fn 传递给子控件,如下所示。
这是父小部件 Fn:
void _changeData({
String areaId,int coastPerPerson,int expandedindex
}){
setState(() {
_areaId = areaId;
_coastPerPerson = coastPerPerson;
_selectedBranchChecked = selectedBranchChecked;
_formatted = formatted;
_showCreateReservationButton = showCreateReservationButton;
_isExpanded = isExpanded;
_expandedindex = expandedindex;
});
}
当我将这个 Fn 传递给子部件时也在下面:
SelectBranchWidget(
branches: _branches,coastPerPerson: _coastPerPerson,areaId: _areaId,selectedBranchChecked: _selectedBranchChecked,formatted: _formatted,isExpanded: _isExpanded,showCreateReservationButton: _showCreateReservationButton,expandedindex: _expandedindex,***changeData: _changeData,***
),
这是我需要再次将数据从它返回给父级的子小部件:
class SelectBranchWidget extends StatefulWidget {
List<RestaurantBranch> branches;
int coastPerPerson;
String areaId;
int selectedBranchChecked;
String formatted;
bool isExpanded;
bool showCreateReservationButton;
int expandedindex;
Function changeData;
SelectBranchWidget(
{this.branches,this.coastPerPerson,this.areaId,this.selectedBranchChecked,this.formatted,this.isExpanded,this.showCreateReservationButton,this.expandedindex,this.changeData,});
@override
_SelectBranchWidgetState createState() => _SelectBranchWidgetState();
}
class _SelectBranchWidgetState extends State<SelectBranchWidget> {
void _changedValues(int i,int branchAreaIndex) {
widget.coastPerPerson = widget.branches[i].branchAreas[branchAreaIndex].costPerSeat;
widget.areaId = widget.branches[i].branchAreas[branchAreaIndex].guid;
print('areaId IS ${widget.areaId}');
widget.selectedBranchChecked = i;
widget.formatted = null;
widget.isExpanded = false;
widget.showCreateReservationButton = false;
widget.expandedindex = -1;
widget.changeData(
areaId: widget.areaId,coastPerPerson: widget.coastPerPerson,selectedBrnachChecked:widget.selectedBranchChecked,formatted: widget.formatted,showCreateReservationButton:widget.showCreateReservationButton,isExpanded:widget.isExpanded,expandedindex: widget.expandedindex
);
}
@override
Widget build(BuildContext context) {
return Container(
decoration: Boxdecoration(
color: Theme.of(context).primaryColorDark,borderRadius: BorderRadius.all(Radius.circular(10))),padding: EdgeInsets.all(8),margin: EdgeInsets.only(left: 16,right: 16),child: Column(
mainAxisSize: MainAxisSize.min,children: [
Align(
alignment: Alignment.centerLeft,child: Text(
'Select Branch',style: TextStyle(
color: Colors.white,fontSize: 20,fontWeight: FontWeight.bold),),SizedBox(
height: 8,Align(
alignment: Alignment.centerLeft,child: Padding(
padding: const EdgeInsets.only(left: 8.0),child: Text(
'Number of branches = ${widget.branches.length}',style: TextStyle(color: Colors.grey,fontSize: 10),SizedBox(
height: 16,ConstrainedBox(
constraints:
BoxConstraints(maxHeight: 230,maxWidth: double.infinity),child: ListView.builder(
shrinkWrap: true,itemCount: widget.branches.length,itemBuilder: (ctx,i) {
return GestureDetector(
onTap: () {
if (widget.branches[i].branchAreas.length == 1) {
_changedValues(i,0);
return;
}
showDialog(
context: context,builder: (BuildContext context) {
return AlertDialog(
backgroundColor: Theme.of(context).backgroundColor,title: Text(
'Select Area',style: TextStyle(
color: Colors.white,content: Container(
decoration: Boxdecoration(
color: Theme.of(context).primaryColorDark,borderRadius: BorderRadius.all(
Radius.circular(10),// height: (_branches[i].branchAreas.length == 1)
// ?70
// : (_branches[i].branchAreas.length == 2)
// ? 100
// :150,width: 100.0,child: ConstrainedBox(
constraints: BoxConstraints(maxHeight: 120),child: ListView.builder(
shrinkWrap: true,itemCount:
widget.branches[i].branchAreas.length,itemBuilder:
(BuildContext context,int index) {
return GestureDetector(
onTap: () {
_changedValues(i,index);
Navigator.of(context).pop();
},child: Padding(
padding: const EdgeInsets.only(
top: 16,left: 36.0,right: 36),child: Column(
crossAxisAlignment:
CrossAxisAlignment.start,children: [
Text(
widget.branches[i]
.branchAreas[index].name,style: TextStyle(
color: Colors.white),Divider(
color: Colors.grey,thickness: 1,],);
},);
});
},child: Card(
elevation: 8,shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12),color: Theme.of(context).backgroundColor,child: Container(
padding: EdgeInsets.all(20),child: Row(
mainAxisSize: MainAxisSize.min,mainAxisAlignment: MainAxisAlignment.spaceBetween,children: [
Text(
widget.branches[i].branchdistrict.name,style: TextStyle(color: Colors.white,fontSize: 16),(widget.selectedBranchChecked == i)
? Container(
height: 40,width: 40,child: Image.asset(
getAssetsName(AssetsImage.checkIcon),fit: BoxFit.cover,)
: Container(
padding: EdgeInsets.only(top: 5,bottom: 5),height: 40,decoration: Boxdecoration(
shape: BoxShape.circle,color: Colors.white,child: SizedBox(),);
},);
}
}
解决方法
您可以使用两种方法来实现这一点。
如果您想从路线返回(从下一个屏幕到上一个),请使用第一个
如果您想在同一屏幕上从其子窗口小部件更改父窗口小部件,请使用第二种方法。
第一种方法(从路线返回一个物体)
为您传递的数据创建一个模型。
class MyModel {
int coastPerPerson;
String areaId;
int selectedBranchChecked;
String formatted;
bool isExpanded;
bool showCreateReservationButton;
int expandedIndex;
Function changeData;
MyModel({
this.areaId,this.coastPerPerson,this.selectedBranchChecked,this.formatted,this.isExpanded,this.showCreateReservationButton,this.expandedIndex,});
}
我假设你的父母看起来像这样。你从父页面导航到 选择BranchWidget页面
class YourParentWidget extends StatefulWidget {
YourParentWidget({Key key}) : super(key: key);
@override
_YourParentWidgetState createState() => _YourParentWidgetState();
}
class _YourParentWidgetState extends State<YourParentWidget> {
navigateAndChangeData(){
Navigator.of(context).push(MaterialPageRoute(builder: (context) {
return SelectBranchWidget();
})).then((value) {
///Use this to get value from next screen to PArent Screen
if(value != null) {
var model = value as MyModel;
//Now you have access to all returning values
//model.areaId
//model.coastPerPerson
//model.selectedBranchChecked
//...
///Make changes accordingly
}
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
///Your UI Conponents....
);
}
}
现在在 SelectBranchWidget Widget 中,您需要在 _changedValues
函数中做的是返回模型值。即
class SelectBranchWidget extends StatefulWidget {
List<RestaurantBranch> branches;
int coastPerPerson;
String areaId;
int selectedBranchChecked;
String formatted;
bool isExpanded;
bool showCreateReservationButton;
int expandedIndex;
Function changeData;
SelectBranchWidget(
{this.branches,this.areaId,this.changeData,});
@override
_SelectBranchWidgetState createState() => _SelectBranchWidgetState();
}
class _SelectBranchWidgetState extends State<SelectBranchWidget> {
void _changedValues(int i,int branchAreaIndex) {
MyModel model = MyModel(
areaId: widget.branches[i].branchAreas[branchAreaIndex].guid,coastPerPerson: widget.branches[i].branchAreas[branchAreaIndex].costPerSeat,selectedBranchChecked: 1,formatted: null,isExpanded: false,showCreateReservationButton: false,expandedIndex: -1
);
Navigator.of(context).pop(model);
}
@override
Widget build(BuildContext context) {
return Container(
decoration: BoxDecoration(
color: Theme.of(context).primaryColorDark,borderRadius: BorderRadius.all(Radius.circular(10))),padding: EdgeInsets.all(8),margin: EdgeInsets.only(left: 16,right: 16),child: Column(
mainAxisSize: MainAxisSize.min,children: [
Align(
alignment: Alignment.centerLeft,child: Text(
'Select Branch',style: TextStyle(
color: Colors.white,fontSize: 20,fontWeight: FontWeight.bold),),SizedBox(
height: 8,Align(
alignment: Alignment.centerLeft,child: Padding(
padding: const EdgeInsets.only(left: 8.0),child: Text(
'Number of branches = ${widget.branches.length}',style: TextStyle(color: Colors.grey,fontSize: 10),SizedBox(
height: 16,ConstrainedBox(
constraints:
BoxConstraints(maxHeight: 230,maxWidth: double.infinity),child: ListView.builder(
shrinkWrap: true,itemCount: widget.branches.length,itemBuilder: (ctx,i) {
return GestureDetector(
onTap: () {
if (widget.branches[i].branchAreas.length == 1) {
_changedValues(i,0);
return;
}
showDialog(
context: context,builder: (BuildContext context) {
return AlertDialog(
backgroundColor: Theme.of(context).backgroundColor,title: Text(
'Select Area',style: TextStyle(
color: Colors.white,content: Container(
decoration: BoxDecoration(
color: Theme.of(context).primaryColorDark,borderRadius: BorderRadius.all(
Radius.circular(10),// height: (_branches[i].branchAreas.length == 1)
// ?70
// : (_branches[i].branchAreas.length == 2)
// ? 100
// :150,width: 100.0,child: ConstrainedBox(
constraints: BoxConstraints(maxHeight: 120),child: ListView.builder(
shrinkWrap: true,itemCount:
widget.branches[i].branchAreas.length,itemBuilder:
(BuildContext context,int index) {
return GestureDetector(
onTap: () {
_changedValues(i,index);
Navigator.of(context).pop();
},child: Padding(
padding: const EdgeInsets.only(
top: 16,left: 36.0,right: 36),child: Column(
crossAxisAlignment:
CrossAxisAlignment.start,children: [
Text(
widget.branches[i]
.branchAreas[index].name,style: TextStyle(
color: Colors.white),Divider(
color: Colors.grey,thickness: 1,],);
},);
});
},child: Card(
elevation: 8,shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12),color: Theme.of(context).backgroundColor,child: Container(
padding: EdgeInsets.all(20),child: Row(
mainAxisSize: MainAxisSize.min,mainAxisAlignment: MainAxisAlignment.spaceBetween,children: [
Text(
widget.branches[i].branchDistrict.name,style: TextStyle(color: Colors.white,fontSize: 16),(widget.selectedBranchChecked == i)
? Container(
height: 40,width: 40,child: Image.asset(
getAssetsName(AssetsImage.checkIcon),fit: BoxFit.cover,)
: Container(
padding: EdgeInsets.only(top: 5,bottom: 5),height: 40,decoration: BoxDecoration(
shape: BoxShape.circle,color: Colors.white,child: SizedBox(),);
},);
}
}
第二种方法(在保留子控件的同时更改父控件)
使您的父小部件的状态类和 changeData
函数公开(即删除状态类名称前的下划线)
即
class YourParentWidget extends StatefulWidget {
YourParentWidget({Key key}) : super(key: key);
@override
YourParentWidgetState createState() => YourParentWidgetState();
}
class YourParentWidgetState extends State<YourParentWidget> {
String _areaId;
int _coastPerPerson;
int _selectedBranchChecked;
String _formatted;
bool _showCreateReservationButton;
bool _isExpanded;
int _expandedIndex;
void changeData({
String areaId,int coastPerPerson,int selectedBranchChecked,String formatted,bool showCreateReservationButton,bool isExpanded,int expandedIndex
}){
setState(() {
_areaId = areaId;
_coastPerPerson = coastPerPerson;
_selectedBranchChecked = selectedBranchChecked;
_formatted = formatted;
_showCreateReservationButton = showCreateReservationButton;
_isExpanded = isExpanded;
_expandedIndex = expandedIndex;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
///Your UI Conponents....
);
}
}
然后将 widget.key
从 YourParentWidget 传递给您的 SelectBranchWidget(如果您在 YourParentWidget 的 UI 中使用它),即
return Scaffold(
body: Column(
children: [
///Your UI Conponents....
SelectBranchWidget(parentKey: widget.key,///... Other PArameters as well
)
],)
);
现在在您的 SelectBranchWidget
小部件中,执行以下操作
class SelectBranchWidget extends StatefulWidget {
GlobalKey<YourParentWidgetState> parentKey;
List<RestaurantBranch> branches;
int coastPerPerson;
String areaId;
int selectedBranchChecked;
String formatted;
bool isExpanded;
bool showCreateReservationButton;
int expandedIndex;
Function changeData;
SelectBranchWidget(
{
this.parentKey,this.branches,int branchAreaIndex) {
widget.coastPerPerson = widget.branches[i].branchAreas[branchAreaIndex].costPerSeat;
widget.areaId = widget.branches[i].branchAreas[branchAreaIndex].guid;
print('areaId IS ${widget.areaId}');
widget.selectedBranchChecked = i;
widget.formatted = null;
widget.isExpanded = false;
widget.showCreateReservationButton = false;
widget.expandedIndex = -1;
///Then do this to make changes to your parent widget's state
widget.parentKey.currentState.changeData(
areaId: widget.areaId,coastPerPerson: widget.coastPerPerson,selectedBrnachChecked:widget.selectedBranchChecked,formatted: widget.formatted,showCreateReservationButton:widget.showCreateReservationButton,isExpanded:widget.isExpanded,expandedIndex: widget.expandedIndex
);
}
@override
Widget build(BuildContext context) {
return Container(
decoration: BoxDecoration(
color: Theme.of(context).primaryColorDark,);
}
}
编辑:您只需要像 YourParentWidget
YourParentWidget(key: GlobalKey<YourParentWidgetState>())
如有错别字请见谅