【问题标题】:Error when selecting a dropdown item in Flutter在 Flutter 中选择下拉项时出错
【发布时间】:2019-02-03 11:38:24
【问题描述】:

我遇到了 Flutter 下拉菜单的问题。当我选择其中一项时,它会引发错误:

引发了另一个异常:'package:flutter/src/material/dropdown.dart':断言失败:第 481 行 pos 15:'value == null || items.where((DropdownMenuItem item) => item.value == value).length == 1': 不正确。

我在搜索,人们告诉我这个错误是因为所选元素不属于原始列表而产生的,但经过一些调试后我可以看到它确实如此。我找不到此错误的根源,因此我将不胜感激。

这是我的代码

FeedCategory 模型

import 'package:meta/meta.dart';

class FeedCategory {
  static final dbId = "id";
  static final dbName = "name";

  int id;
  String name;

  FeedCategory({this.id, @required this.name});

  FeedCategory.fromMap(Map<String, dynamic> map)
      : this(
    id: map[dbId],
    name: map[dbName],
  );

  Map<String, dynamic> toMap() {
    return {
      dbId: id,
      dbName: name,
    };
  }

  @override
  String toString() {
    return 'FeedCategory{id: $id, name: $name}';
  }
}

小部件

import 'package:app2date/repository/repository.dart';
import 'package:app2date/model/FeedSource.dart';
import 'package:app2date/model/FeedCategory.dart';
import 'package:app2date/util/ui.dart';
import 'package:flutter/material.dart';

class ManageFeedSource extends StatefulWidget {
  ManageFeedSource({Key key, this.feedSource}) : super(key: key);

  final FeedSource feedSource;

  @override
  _ManageFeedSource createState() => new _ManageFeedSource();
}

class _ManageFeedSource extends State<ManageFeedSource> {
  FeedCategory _feedCategory;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('New Feed'),
      ),
      body: new FutureBuilder(
        future: Repository.get().getFeedCategories(),
        builder: (BuildContext context, AsyncSnapshot snapshot) {
          List<FeedCategory> categoriesList = snapshot.data;
          if (categoriesList != null) {
            return new DropdownButton<FeedCategory>(
              hint: Text('Choose category...'),
              value: _feedCategory,
              items: categoriesList.map((FeedCategory category) {
                return DropdownMenuItem<FeedCategory>(
                  value: category,
                  child: Text(category.name),
                );
              }).toList(),
              onChanged: (FeedCategory category) {
                print('Selected: $category');
                setState(() {
                  _feedCategory = category;
                });
              },
            );
          } else {
            return Container(
              decoration: new BoxDecoration(color: Colors.white),
            );
          }
        },
      ),
    );
  }

  @override
  void initState() {
    super.initState();
  }
}

存储库 getFeedCategories 方法

Future<List<FeedCategory>> getFeedCategories() async {
  return await database.getFeedCategories();
}

数据库 getFeedCategories 方法

Future<List<FeedCategory>> getFeedCategories() async {
  var dbClient = await db;
  var query = "SELECT * FROM $feedCategoryTableName;";
  var result = await dbClient.rawQuery(query);
  List<FeedCategory> feedCategories = [];
  for (Map<String, dynamic> item in result) {
    feedCategories.add(new FeedCategory.fromMap(item));
  }
  return feedCategories;
}

categoriesList 内容和选择的类别(调试器)

【问题讨论】:

  • 所选项目需要是选择列表之一。
  • 我一直在调试,选中的项目属于选择列表,可能是我误会了什么
  • 您能否在遇到问题时添加您拥有的类别列表?这可能会有所帮助...
  • 是的,我现在添加它
  • 我添加了相关信息

标签: flutter dropdown selected


【解决方案1】:

我想我已经解决了您的问题。这源于您使用 FutureBuilder 的方式。

我认为是这样的:

  1. 您的应用程序正在运行。它调用 getFeedCategories()
  2. Future 完成,列表建立,等等:

    obj 123 ==&gt; FeedCategory(Prueba), obj 345 ==&gt; FeedCategory(Categories 2)

  3. 从下拉列表中选择项目,调用 setState()

    您的 _feedCategory 现在等于 obj 123 ==&gt; FeedCategory(Prueba)

  4. 小部件已重建。它再次调用 getFeedCategories()

  5. 未来完成,列表建立等,包含以下项目

    obj 567 ==&gt; FeedCategory(Prueba), obj 789 ==&gt; FeedCategory(Categories 2)

  6. Dropdown 测试 items.where((DropdownMenuItem item) =&gt; item.value == value).length == 1,但长度 == 0,因为找不到 obj 123 ==&gt; FeedCategory(Prueba)

您的问题有几个解决方案。一种方法是将equals operator 添加到您的FeedCategory 类中,用于比较类别和/或id。

另一种方法是将futurebuilder中使用的Future与更改的部分分开-您可以通过将future保留为成员变量(可能在initState中实例化它?)来做到这一点,或者通过使内部部分builder 到它自己的 Stateful 小部件中(在这种情况下,您可以将 ManageFeedSource 设为 StatelessWidget)。我推荐最后一个选项。

如果这不能解决您的问题,请告诉我,但我很确定这就是它正在做它正在做的事情的原因。

【讨论】:

  • 请注意,123, 345, 567, 789 是我试图表示 FeedCategories 是表面上相同对象的不同实例。
  • 是的,这就是问题所在!非常感谢
  • 是的,将运算符添加到您的自定义类是克服这种情况的最佳方法。谢谢
  • @rmtmckenzie 得到这个错误 - "'items == null || items.isEmpty || value == null || items.where((DropdownMenuItem item) { return item.value = = value; }).length == 1' 通过映射我正在将数据添加到下拉列表中,它的工作正常,但是当我在州代码依赖区等上更新状态时会崩溃等等..
【解决方案2】:

要完成rmtmckenzie answer,您应该将以下代码放入您的 FeedCategory 对象中:

bool operator ==(o) => o is FeedCategory && o.name == name;
int get hashCode => name.hashCode;

编辑:link 解释了 Flutter 中 hashCode 的用途

【讨论】:

  • 感谢添加,非常有用。您是否有任何解释该代码的文档?我不明白为什么我们还要重写 hashCode 方法
  • @Robouste 你可以查看this link,它解释了 Flutter 中 hashCode 的用途
  • 拯救了我的一天!花了4个小时。
【解决方案3】:

当我使用实际上不在下拉列表中的值初始化下拉列表时出现此错误,该错误消息中并不清楚。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-27
    • 2023-01-08
    • 1970-01-01
    • 2019-02-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多