英文:
Navigating to the screen with dropdown twice, gives the following error: Either zero or 2 or more [DropdownMenuItem] were detected with the same value
问题
以下是翻译好的部分:
- "I know what causes this error, but I couldn't figure it out in this case." 翻译为 "我知道导致这个错误的原因,但在这种情况下我无法解决它。"
- "Here is the scenario, when I navigate to the screen that contains the dropdown for the first time, the dropdown works properly. However, when I navigate back and renavigate to the same screen(for the second time) the following error is thrown. Any suggestion?" 翻译为 "以下是情景,当我首次导航到包含下拉框的屏幕时,下拉框正常工作。然而,当我返回并再次导航到相同的屏幕(第二次)时,出现以下错误。有什么建议吗?"
- "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" 翻译为 "应该有一个与[DropdownButton]的值完全相符的项目:CategoryDto{ categoryId: cc050c58-876a-4245-9531-be8553c7ae07, name: Masa Oyunları,}。检测到零个或2个或更多[DropdownMenuItem]具有相同的值。"
- "The following 4 code snippets are in the parent widget where I call the dropdown. (I want to publish only the relevant parts for convenience.)" 翻译为 "以下的4个代码片段位于我调用下拉框的父部件中。 (我只想发布方便的相关部分。)"
- "This is my parent widget where I call the dropdown. (in parent widget)" 翻译为 "这是我调用下拉框的父部件。 (在父部件中)"
- "initialize the doprdown value as null. (in parent widget)" 翻译为 "将下拉框的值初始化为null。 (在父部件中)"
- "if the API returns the list of categories, then set the first value as
_selectedCategory
. (in parent widget)" 翻译为 "如果API返回类别列表,那么将第一个值设置为_selectedCategory
。 (在父部件中)" - "
selectCategory
callback function. (in parent widget)" 翻译为 "selectCategory
回调函数。 (在父部件中)" - "And this is my CategoryDropdown." 翻译为 "这是我的CategoryDropdown。"
请注意,您的代码示例包含HTML实体编码(如"
和<
),这些编码在中文文本中不需要翻译,仅供代码解释和格式的目的。如果需要更多帮助或其他部分的翻译,请告诉我。
英文:
I know what causes this error, but I couldn't figure it out in this case.
Here is the scenario, when I navigate to the screen that contains the dropdown for the first time, the dropdown works properly. However, when I navigate back and renavigate to the same screen(for the second time) the following error is thrown. Any suggestion?
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'
The following 4 code snippets are in the parent widget where I call the dropwdown. (I want to publish only the relevant parts for convenience.)
This is my parent widget where I call the dropdown.(in parent widget)
state.categories.isNotEmpty
? CategoryDropdown(
selectedCategory: _selectedCategory!,
handleSelection: selectCategory,
labelText: "Category",
categories: state.categories)
: Container(),
initialize the doprdown value as null. (in parent widget)
EventCategory? _selectedCategory;
if the API returns the list of categories, then set the first value as _selectedCategory
. (in parent widget)
else if (state is CategoryListSuccess) {
_selectedCategory ??= state.categories.first;
selectCategory
callback function.(in parent widget)
selectCategory(EventCategory eventCategory) {
setState(() {
_selectedCategory = eventCategory;
});
}
And this is my CategoryDropdown.
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
得分: 2
感谢 @pskink,我解决了这个问题。实际上,问题不在我的Flutter代码中,而是在我的Java Spring Boot的REST API中。我生成了一个虚拟的类别列表API。
以下代码是错误的。为什么?因为每当我从客户端(Flutter应用程序)调用getCategories
时,它都会生成一个新的UUID
并将其发送给客户端。这就是为什么当我首次导航到带有下拉框的屏幕时,它会发出API调用并选择第一个返回的元素。然后,当我返回并再次导航到相同的屏幕时,我再次从API获取类别列表。但是,由于这次进行了第二次调用,因此会生成一个新的UUID并传递。这就是为什么第一次的UUID与第二次不同的原因。DropDown在这一点上引发了断言错误,因为尽管两个类别的名称相同,但第二个类别的ID与第一个类别不同。这就是为什么无法实现对象相等性。
为了修复这段代码,我将我的列表设为静态并传递给客户端,如下所示。
static List<Category> categories = fillList();
@GetMapping
public List<Category> getCategories() throws ResourceNotFoundException {
return categories;
}
private static List<Category> fillList() {
List<Category> list = new ArrayList<>();
list.add(new Category(UUID.randomUUID(), "Category1"));
list.add(new Category(UUID.randomUUID(), "Category2"));
list.add new Category(UUID.randomUUID(), "Category3"));
return list;
}
请注意,这是代码的翻译部分,不包含任何其他内容。
英文:
Thanks to @pskink, I could have solved this. Actually, the problem is not in my flutter code. It's in my rest API, which is written in Java Spring Boot. I generated a dummy category list API.
The following code is wrong. Why? Because each time when I call getCategories
from my client(flutter app), it generates a new UUID
and sends it to the client. That's why when I first navigate to the screen with dropdown, it makes an API call and selects the first returned element. Then, when I navigate back and, renavigate to the same screen again. I fetch the categories list from the API again. However, since I make a second call this time a new UUID is generated and passed. That's why in the first time the UUID is different from the second time. DropDown throws an assertion error at that point because even though, the name of the two categories are the same, the second one's id is different from the first one. That's why object equality could not be achieved.
@GetMapping
public List<Category> getCategories() throws ResourceNotFoundException {
List<Category> list = new ArrayList<>();
list.add(new Category(UUID.randomUUID(),"Category1")); //each call creates a new UUID
list.add(new Category(UUID.randomUUID(),"Category2"));
list.add(new Category(UUID.randomUUID(),"Category3"));
return list;
}
To fix this code I made my list static and pass to the client as follows.
static List<Category> categories = fillList();
@GetMapping
public List<Category> getCategories() throws ResourceNotFoundException {
// throw new ResourceNotFoundException("Saçamlaamaa");
return categories;
}
private static List<Category> fillList(){
List<Category> list = new ArrayList<>();
list.add(new Category(UUID.randomUUID(),"Category1"));
list.add(new Category(UUID.randomUUID(),"Category2"));
list.add(new Category(UUID.randomUUID(),"Category3"));
return list;
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论