You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter下拉框报错:ProductModel实例匹配项数量异常

Flutter分类联动下拉框产品选择报错解决方法

问题现象

开发分类联动产品下拉框时,选择分类后产品列表按分类过滤展示,但选择产品时触发报错:

There should be exactly one item with [DropdownButton]'s value: Instance of 'ProductModel'. Either zero or 2 or more [DropdownMenuItem]s were detected with the same value

直接使用全量产品列表无报错,但无法实现分类筛选需求。

问题原因

报错核心在于ProductModel对象的相等性判断逻辑:

  • 切换分类时,_filteredstoreProdList是通过where过滤生成的新列表,默认情况下Dart对象的==运算符比较的是内存地址而非实际数据。
  • 若之前选中过某个ProductModel,切换分类后新过滤列表中即使有数据相同的产品,也会因内存实例不同,导致DropdownButton无法匹配到对应的MenuItem,或误判为多个相同值,最终抛出错误。

解决方案

1. 为ProductModel重写相等性判断

在ProductModel类中重写==运算符和hashCode,基于产品的唯一标识(比如id)判断对象相等:

class ProductModel {
  final String id;
  final String name;
  final String categoryId;
  // 其他字段根据实际情况添加

  ProductModel({
    required this.id,
    required this.name,
    required this.categoryId,
  });

  @override
  bool operator ==(Object other) {
    if (identical(this, other)) return true;
    
    return other is ProductModel &&
        other.id == id &&
        other.runtimeType == runtimeType;
  }

  @override
  int get hashCode => id.hashCode;
}

2. 切换分类时重置选中产品

在分类下拉框的onChanged回调中,切换分类后将选中的产品置为null,确保DropdownButton的value始终存在于当前过滤后的产品列表中:

onChanged: (CategoryModel value) {
  setState(() {
    this._selectedCategory = value;
    this._filteredstoreProdList = widget.userData.products
        .where((data) => data.categoryId == value.id)
        .toList();
    // 重置选中产品,避免旧选中项不在新过滤列表中
    this._selectedProducts = null;
  });
},

修改后的完整代码片段

分类下拉框

Widget _prepareCategoryDDL() {
  return Container(
    width: 350,
    decoration: BoxDecoration(
      color: Colors.white,
      borderRadius: BorderRadius.circular(10),
      boxShadow: [
        BoxShadow(
            color: Color.fromRGBO(225, 95, 27, .3),
            blurRadius: 20,
            offset: Offset(0, 10))
      ],
    ),
    child: DropdownButton<CategoryModel>(
      hint: Text("  Categories"),
      value: this._selectedCategory,
      onChanged: (CategoryModel value) {
        setState(() {
          this._selectedCategory = value;
          this._filteredstoreProdList = widget.userData.products
              .where((data) => data.categoryId == value.id)
              .toList();
          // 重置选中产品
          this._selectedProducts = null;
        });
      },
      items: widget.userData.categories.map((CategoryModel category) {
        return DropdownMenuItem<CategoryModel>(
          value: category,
          child: Row(
            children: <Widget>[
              Text(
                "  " + category.name,
                style: TextStyle(color: Colors.black),
              ),
            ],
          ),
        );
      }).toList(),
    ),
  );
}

产品下拉框(无需额外修改)

Widget _prepareProductsDDL() {
  return Container(
    width: 350,
    decoration: BoxDecoration(
      color: Colors.white,
      borderRadius: BorderRadius.circular(10),
      boxShadow: [
        BoxShadow(
          color: Color.fromRGBO(225, 95, 27, .3),
          blurRadius: 20,
          offset: Offset(0, 10),
        ),
      ],
    ),
    child: DropdownButton<ProductModel>(
      hint: Text("  Product"),
      value: this._selectedProducts,
      onChanged: (ProductModel value) {
        setState(
          () {
            this._selectedProducts = value;
          },
        );
      },
      items: this._filteredstoreProdList.map((ProductModel product) {
        return DropdownMenuItem<ProductModel>(
          value: product,
          child: Row(
            children: <Widget>[
              Text(
                product.name.length > 30
                    ? "  " + product.name.substring(0, 30)
                    : product.name,
                style: TextStyle(color: Colors.black),
              ),
            ],
          ),
        );
      }).toList(),
    ),
  );
}

内容的提问来源于stack exchange,提问作者akshay ramagiri

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 11:55:47