在Flutter中选择下拉项时出错

Alb*_*dez 8 selected dropdown flutter

我对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}';
  }
}
Run Code Online (Sandbox Code Playgroud)

小部件

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();
  }
}
Run Code Online (Sandbox Code Playgroud)

存储库getFeedCategories方法

Future<List<FeedCategory>> getFeedCategories() async {
  return await database.getFeedCategories();
}
Run Code Online (Sandbox Code Playgroud)

数据库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;
}
Run Code Online (Sandbox Code Playgroud)

分类列出内容和所选分类(调试器) 在此处输入图片说明

rmt*_*zie 8

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

我认为这是怎么回事:

  1. 您的应用正在运行。它调用getFeedCategories()
  2. 将来完成,并建立列表,并包含以下各项:

    obj 123 ==> FeedCategory(Prueba)obj 345 ==> FeedCategory(Categories 2)

  3. 您从下拉菜单中选择项目,调用setState()

    您的_feedCategory现在等于 obj 123 ==> FeedCategory(Prueba)

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

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

    obj 567 ==> FeedCategory(Prueba)obj 789 ==> FeedCategory(Categories 2)

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

有两种解决方案来解决您的问题。其中之一是增加一个平等经营你的FeedCategory类比较类别和/或ID。

另一个方法是将futurebuilder中使用的Future与发生变化的部分分开-您可以通过将future保留为成员变量(可以在initState中实例化它)来实现,也可以通过将builder的内部部分放入其中来实现。自己的有状态小部件(在这种情况下,您可以使ManageFeedSource成为StatelessWidget)。我建议最后一个选择。

让我知道这是否不能解决您的问题,但是我很确定这就是它正在做的事情的原因。


Que*_*aux 5

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

bool operator ==(o) => o is FeedCategory && o.name == name;
int get hashCode => name.hashCode;
Run Code Online (Sandbox Code Playgroud)

编辑:一个链接,解释了在 Flutter 中 hashCode 的用途