未处理的异常:<int>从 Navigator.pop() 返回值时,类型"_DropdownRouteResult"不是类型"int?"的子类型。



DropdownButtonFormField中,我有一个从Provider填充的标准DropdownMenuItems列表;添加新的";按钮,该按钮按下包含CCD_ 4的CCD_。提交后,表单通过Provider将新数据异步插入数据库,并在对Navigator.pop()的调用中返回数据库id。

预期的行为是,pop((回调应该将下拉字段的值设置为返回的int值,并且应该关闭下拉菜单,并反映更新后的值。

在下面的代码片段中,我有两个版本的";添加新的";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是CCD_ 8。无论我使用async/await还是.then((语法,都会发生这种行为。

我不知道这是由于先发制人的类型检查,还是由于我遗漏了一些东西而导致等待Promise的奇怪失败。

相关代码如下:


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'),
    );
  }
}

编辑:根据@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)

我想在相关的MaterialPageRoute中添加一个int?类型的arg,但收到了相同的结果。

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.
        ],
      ),
    );
  }
}

尝试指定期望从Navigator.push返回的类型,以及在AddNewTeaProducerRoute中Navigator.pop时要返回的类型。

你的代码应该看起来像:

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);

在此之后,您不应该得到任何强制转换异常。

最新更新