我知道这个错误的原因,但是我在这种情况下找不到原因。下面是一个场景,当我第一次导航到包含下拉菜单的屏幕时,下拉菜单工作正常。但是,当我返回并重新导航到同一个屏幕(第二次)时,抛出了以下错误。有什么建议吗?
There should be exactly one item with [DropdownButton]'s value: CategoryDto{ categoryId: cc050c58-876a-4245-9531-be8553c7ae07, name: Masa Oyunları,}.
Either zero or 2 or more [DropdownMenuItem]s were detected with the same value
'package:flutter/src/material/dropdown.dart':
Failed assertion: line 1584 pos 15: 'items == null || items.isEmpty || value == null ||
items.where((DropdownMenuItem<T> item) {
return item.value == value;
}).length == 1'
下面4个代码片段位于我调用下拉列表的父小部件中(为了方便起见,我只想发布相关部分)。
这是我的父小部件,我在这里调用下拉菜单。(在父小部件中)
state.categories.isNotEmpty
? CategoryDropdown(
selectedCategory: _selectedCategory!,
handleSelection: selectCategory,
labelText: "Category",
categories: state.categories)
: Container(),
初始化doprdown值为空.(在父窗口小部件中)EventCategory? _selectedCategory;
如果API返回类别列表,则将第一个值设置为_selectedCategory
。(在父小部件中)
else if (state is CategoryListSuccess) {
_selectedCategory ??= state.categories.first;
selectCategory
回调函数。(在父小部件中)
selectCategory(EventCategory eventCategory) {
setState(() {
_selectedCategory = eventCategory;
});
}
这是我的分类下拉列表。
class CategoryDropdown extends StatelessWidget {
final String labelText;
final List<EventCategory> categories;
final EventCategory selectedCategory;
final Function handleSelection;
const CategoryDropdown(
{Key? key,
required this.labelText,
required this.categories,
required this.selectedCategory,
required this.handleSelection})
: super(key: key);
@override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsets.fromLTRB(6, 0, 0, 0),
child: Text(
labelText,
style: Theme.of(context)
.textTheme
.titleMedium
?.copyWith(color: Theme.of(context).colorScheme.secondary),
),
),
Material(
elevation: 10,
borderRadius: BorderRadius.circular(10),
child: DropdownButtonFormField<EventCategory>(
value: selectedCategory,
icon: const Icon(Icons.expand_more),
elevation: 10,
onChanged: (EventCategory? category) => handleSelection(category),
items: categories.map<DropdownMenuItem<EventCategory>>(
(EventCategory category) {
print(selectedCategory);
return DropdownMenuItem<EventCategory>(
value: category,
child: Text(category.name!),
);
}).toList(),
),
),
],
);
}
}
1条答案
按热度按时间ljsrvy3e1#
多亏了@pskink,我本来可以解决这个问题的,其实问题不在我的flutter代码,在我的rest API,用Java Sping Boot 写的,我生成了一个虚拟的类别列表API。
下面的代码是错误的。为什么?因为每次我从客户端调用
getCategories
时(flutter应用),它生成一个新的UUID
并发送给客户端。这就是为什么当我第一次使用下拉菜单导航到屏幕时,它会进行API调用并选择第一个返回的元素。然后,当我向后导航时,再次导航到相同的屏幕。我再次从API中获取类别列表。但是,因为我进行了第二次调用,这一次生成并传递了一个新的UUID,这就是为什么第一次调用的UUID与第二次调用的UUID不同。此时DropDown抛出一个Assert错误,因为尽管两个类别的名称相同,但第二个类别的id与第一个类别的id不同,这就是无法实现对象平等的原因。为了修复这段代码,我将列表设置为静态,并按如下方式传递给客户端。