导航后,下拉菜单项未重置

时间:2020-06-28 06:05:19

标签: flutter dart

我正在使用StatefulWidget作为当前的仪表板页面。我在initState中调用后端,并在响应中创建下拉项。这部分工作正常!

我的问题是当我导航离开并返回页面时,出现以下错误:

There should be exactly one item with [DropdownButton]'s value: 5eb8e4670ae9b245c86b752b. 
Either zero or 2 or more [DropdownMenuItem]s were detected with the same value
'package:flutter/src/material/dropdown.dart':
Failed assertion: line 827 pos 15: 'items == null || items.isEmpty || value == null ||
              items.where((DropdownMenuItem<T> item) {
                return item.value == value;
              }).length == 1'

调试之后,我看到我的下拉列表保留了上次的内容,因此当我返回页面并尝试从后端生成新的Item时,我不能,因为它已经在下拉列表中了。 / p>

我想在离开时破坏我的下拉菜单,但是我不知道该怎么做,我已经在使用dispose了,但是重置下拉菜单似乎还不够。

这是我此页面的代码,我将不胜感激,Flutter还是我的新手!谢谢!

信息中心:

class MyDashboard extends StatefulWidget {
  MyDashboardState createState() => MyDashboardState();
}

class MyDashboardState extends State<MyDashboard> {

  Future<List<dynamic>> loadAll() async {
    DateTime now = new DateTime.now();
    var model = Provider.of<DashboardModel>(context);

    try {
      final resp = await dio.post("/endpoint", data: {"date": date.millisecond});
      model.addArray(resp.data);
      return resp.data;

    } catch (err) {
      return Future.error(err);
    }
  }

  @override
  void initState() {
    super.initState();
    new Future.delayed(Duration.zero,() {
      this.loadAll();
    });
    
  }

  @override
  Widget build(BuildContext context) {
    var model = Provider.of<DashboardModel>(context);

    print('LIST LENGTH: ' + model.getList().length.toString());

    return Scaffold(
      appBar: _MyAppBar(),
      body: Center(
        child: model.getListAsItems().length == 0 ? KidCreate() : KidSelect(),
        ),
      )
    );
  }
}

孩子选择:

class KidSelect extends StatefulWidget {
  _KidSelectState createState() => _KidSelectState();
}

String _mySelection;

class _KidSelectState extends State<KidSelect> {
  List<DropdownMenuItem<String>> list;

  @override
  void dispose() {
    // Clean up the controller when the widget is disposed.
    list = new List();
    _mySelection = null;
    super.dispose();
  }

  Widget _buildSelect() {

    var model = Provider.of<DashboardModel>(context);

    _mySelection = _mySelection == null ? model.getList()[0].id.toString() : _mySelection;
    list = model.getListAsItems();

    return DropdownButton<String>(
        hint: new Text("Select"),
        value: _mySelection,
        onChanged: (String newValue) {
          setState(() {
            _mySelection = newValue;
          });
        },
        items: list,
      );
  }


  @override
  Widget build(BuildContext context) {
    return Form(
      child: Column(
          children: <Widget>[
            _buildSelect(),
          ]
        )
    );
  }
}

1 个答案:

答案 0 :(得分:0)

基于Vilsad P P的注释,使用本地状态而不是提供程序可以解决此问题。但是后来我意识到,由于实现了其他功能,我需要使用提供程序,因此我试图找出它无法正常工作的原因,我想我找到了它!

在导航时,模型提供者仪表板会将我的列表保存在内存中,因此当我向后导航时,它将第二次将值添加到列表中,并且在尝试下拉列表时会崩溃。为了防止这种情况,当我将我的api调用中的信息设置为模型时,而不是仅添加信息,而是在此之前重置了列表,因此列表就像新的一样!

我遇到的另一个问题是默认情况下下拉列表的选择,我试图将列表的第一项置于选中状态,但是在列表完全创建之前,我做得太早了,所以我更改了位置我将选择内容初始化为initState,并在api调用中添加了一个wait,以便它在分配我的第一个结果之前等待!

@override
  void initState() {
    super.initState();
    new Future.delayed(Duration.zero,() async {
      await this.loadAll();
      var model = Provider.of<DashboardModel>(context);
      _mySelection = model.getList().length > 0 ? model.getList()[0].id.toString() : null;
    });
  }

一切似乎都按照现在的方式运行!多亏了Vilsad,我才能够更好地理解颤振的原理!