Flutter DropdownButton触发items/value相关断言错误的问题求助
看起来你遇到的是Flutter DropdownButton里很常见的对象相等性判断问题,我来帮你分析一下原因和解决办法:
问题根源
你看到的这个断言错误,本质是DropdownButton在检查选中的value是否存在于items列表中时,没有找到唯一匹配的项——但你调试时明明看到选中项在列表里,这是因为默认情况下,Dart的对象比较是引用比较,而不是内容比较。
你的_selectedTerminTyp是通过objectBox.getTerminTypById(1)获取的,而_terminTypen列表里的项是通过objectBox.getAllTerminTypen()映射生成的。这两个对象虽然id和name完全一样,但它们是内存中不同的对象引用,所以DropdownButton用item.value == value判断时,会认为这两个对象不相等,导致where查询返回的结果长度不是1,触发了断言。
解决方案
最通用且推荐的解决方式是,在你的TerminTypDetails类中重写==运算符和hashCode方法,让Dart根据对象的内容(这里用唯一标识id)来判断相等性:
@Entity() class TerminTypDetails { @Id(assignable: true) int id = 0; String name; TerminTypDetails({required this.name, required this.id}); factory TerminTypDetails.fromJson(Map<String, dynamic> json) { return TerminTypDetails(id: int.parse(json['id']), name: json['name']); } Map<String, dynamic> toJson() { return {"id": id, "name": name}; } // 重写==运算符,基于id判断对象相等 @override bool operator ==(Object other) => identical(this, other) || other is TerminTypDetails && runtimeType == other.runtimeType && id == other.id; // 重写hashCode,基于id生成(和==逻辑保持一致) @override int get hashCode => id.hashCode; }
替代方案(临时解决)
如果你不想修改实体类,也可以确保选中的对象是直接从_terminTypen列表中获取的引用,比如把初始化_selectedTerminTyp的代码改成:
// 从已有的_terminTypen列表中找到id为1的项 _selectedTerminTyp = _terminTypen.firstWhere((item) => item.value.id == 1).value;
这种方式能保证选中的对象和列表里的项是同一个引用,也能绕过断言错误,但不如重写==和hashCode的方案通用——毕竟后续你在其他地方比较TerminTypDetails对象时,也会需要正确的相等性判断。
备注:内容来源于stack exchange,提问作者Philipp Lauer

