在DropdownButtonFormField中,我有一个从提供程序中填充的标准DropdownMenuItems列表和一个"Add“按钮,该按钮按下包含Form的MaterialRoute。提交时,表单通过Provider异步将新数据插入到数据库,并在对Navigator.pop()的调用中返回db id。
预期的行为是pop()回调应该将下拉字段的值设置为返回的int值,并关闭下拉菜单,并反映更新后的值。
在下面的代码片段中,我有两个版本的"Add“DropdownMenuItem。“工作”版本按照预期执行,但在按下下拉菜单时不会关闭(也像预期的那样,因为它是一个按钮,而不是一个正常的下拉元素)。
“损坏”版本未能推动新的路线,并抛出
E/flutter (24895): [ERROR:flutter/lib/ui/ui_dart_state.cc(198)] Unhandled Exception: type '_DropdownRouteResult<int>' is not a subtype of type 'int?'
E/flutter (24895): #0 _TeaProducerFormFieldState.build.<anonymous closure>.<anonymous closure>.<anonymous closure> (package:teavault/screens/stash/teaform.dart:70:15)
E/flutter (24895): #1 State.setState (package:flutter/src/widgets/framework.dart:1109:30)
E/flutter (24895): #2 _TeaProducerFormFieldState.build.<anonymous closure>.<anonymous closure> (package:teavault/screens/stash/teaform.dart:69:13)
E/flutter (24895): #3 _rootRunUnary (dart:async/zone.dart:1434:47)
E/flutter (24895): #4 _CustomZone.runUnary (dart:async/zone.dart:1335:19)这里提到的L70是_selectedValue = value;。无论我使用异步/等待还是.then()语法,都会发生这种行为。
我不知道这是因为一次先发制人的检查,还是因为我错过了一些东西而无法等待承诺。
有关守则如下:
class _TeaProducerFormFieldState extends State<TeaProducerFormField> {
int? _selectedValue;
@override
Widget build(BuildContext context) {
final teaProducers = Provider.of<TeaProducerCollectionModel>(context).items;
final teaProducerListItems = teaProducers.map((producer) => DropdownMenuItem<int>(
value: producer.id,
child: Text(producer.name),
)).toList();
final workingAddNewTeaProducerButton = DropdownMenuItem<int>(child: TextButton(
onPressed: () async {
final int newValue = await Navigator.push(context, AddNewTeaProducerRoute());
setState(() {
_selectedValue = newValue;
});
},
child: Text('Add New Manufacturer')));
final brokenAddNewTeaProducerButtion = DropdownMenuItem<int>(
onTap: () {
Navigator.push(context, AddNewTeaProducerRoute()).then((value) {
setState(() {
_selectedValue = value;
});
});
},
value: 0,
child: const Text('Add New Manufacturer'));
return DropdownButtonFormField(
value: _selectedValue,
items: teaProducerListItems + [brokenAddNewTeaProducerButtion],
// child: addNewTeaProducerButton)],
onChanged: (_) {},
hint: Text('Select a manufacturer'),
);
}
}编辑:在修改per @Axel的建议并为清晰起见直接插入子树内容之后,我有以下内容,但仍然收到
When the exception was thrown, this was the stack:
#0 LocalHistoryRoute.didPop (package:flutter/src/widgets/routes.dart)
#1 _RouteEntry.handlePop (package:flutter/src/widgets/navigator.dart:2896:16)
#2 NavigatorState._flushHistoryUpdates (package:flutter/src/widgets/navigator.dart:3868:22)
#3 NavigatorState.pop (package:flutter/src/widgets/navigator.dart:4910:7)
#4 Navigator.pop (package:flutter/src/widgets/navigator.dart:2432:27)
#5 _DropdownMenuItemButtonState._handleOnTap (package:flutter/src/material/dropdown.dart:148:15)我想将int?类型的arg添加到相关的MaterialPageRoute中,但是得到了相同的结果。
final brokenAddNewTeaProducerButton = DropdownMenuItem<int>(
onTap: () {
Navigator.push<int?>(context, MaterialPageRoute(
builder: (BuildContext context) =>
Scaffold(
appBar: AppBar(
iconTheme: IconThemeData(color: Colors.white),
title: Text('Define new Manufacturer'),
),
body: Column(
children: <Widget>[
Expanded(
flex: MediaQuery.of(context).orientation == Orientation.portrait ? 4 : 1,
child: Container(),
),
Expanded(
flex: 16,
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 50.0),
child: const TeaProducerForm(),
),
),
],
)
))).then((value) {
setState(() {
_selectedValue = value;
});
});
},
value: 0,
child: const Text('Add New Manufacturer'));
//[...]
class TeaProducerFormState extends State<TeaProducerForm> {
final _formKey = GlobalKey<FormState>();
String? fullName;
String? shortName;
@override
Widget build(BuildContext context) {
// Build a Form widget using the _formKey created above.
return Form(
key: _formKey,
child: Column(
children: <Widget>[
TextFormField(
onSaved: ((value) {fullName = value;}),
decoration: const InputDecoration(
hintText: 'Enter full name',
labelText: 'Full Name'
),
),
TextFormField(
onSaved: ((value) {shortName = value;}),
decoration: const InputDecoration(
hintText: 'Enter abbreviated name',
labelText: 'Short Name'
),
validator: ((value) {
if ((value ?? '').length > 6 ) {
return 'Please enter a name with six or fewer characters';
} else if ((value ?? '').isEmpty ) {
return 'Please enter a name with one or more characters';
}
}),
),
ElevatedButton(
onPressed: () async {
if (_formKey.currentState?.validate() ?? false) {
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text('Saving new manufacturer...')),);
_formKey.currentState?.save();
final teaProducers = Provider.of<TeaProducerCollectionModel>(context, listen: false);
teaProducers.insert(TeaProducer(
name: fullName!,
shortName: shortName!
)).then((value) {
print('added tea as id $value');
ScaffoldMessenger.of(context).clearSnackBars();
Navigator.pop<int?>(context, value);
});
}
},
child: const Text('Submit'))
// Add TextFormFields and ElevatedButton here.
],
),
);
}
}发布于 2022-07-22 08:47:08
尝试指定您期望从Navigator.push中返回的类型以及在Navigator.pop中AddNewTeaProducerRoute中希望返回的类型。
您的代码应该如下所示:
final brokenAddNewTeaProducerButtion = DropdownMenuItem<int>(
onTap: () {
Navigator.push<int?>(context, AddNewTeaProducerRoute()).then((value) {
setState(() {
_selectedValue = value;
});
});
},
value: 0,
child: const Text('Add New Manufacturer'));在AddNewTeaProducerRoute内部,请做:
Navigator.pop<int?>(context, value);在此之后,您不应该得到任何强制转换异常。
https://stackoverflow.com/questions/73076016
复制相似问题