Flutter Dart中List<Map>的搜索实现及搜索栏过滤列表失效问题排查
Flutter Dart 实现 List
我来帮你排查下这段代码的问题,然后给你靠谱的实现方案~
你的代码存在的几个关键问题:
- 直接修改并清空原列表,导致数据永久丢失:你在遍历
offersList的时候调用了offersList.clear(),这会立刻清空当前列表,遍历过程直接中断,而且原始的所有数据都没了——下次搜索的时候根本没有数据可以过滤了。 - 精确匹配过于严格:用
map["foodname"] == query只能匹配和输入内容完全一致的结果,用户输入部分关键词(比如输入“汉堡”想找“牛肉汉堡”)的时候根本搜不到,不符合搜索栏的常规使用需求。 - 逻辑错误导致结果异常:每次找到一个匹配项就调用
setState,而且已经清空了原列表,最终就算有多个匹配项,也只会保留最后一个(如果有的话),同时频繁的setState还会影响性能。
正确的实现思路与代码
核心原则是:保留原始的完整数据源,不要直接修改它,每次搜索都从原始数据中过滤出匹配项,再更新用于显示的列表。
第一步:定义两个列表变量
// 保存原始的所有数据,初始化时从接口或本地赋值 List<Map> originalOffersList = []; // 用于UI显示的过滤后列表,初始时和原始数据一致 List<Map> offersList = [];
第二步:实现搜索过滤方法
这里提供两种实现方式,你可以选自己习惯的:
方式1:遍历原始列表收集匹配项(直观易懂)
void filterOffers(String query) { // 如果搜索关键词为空,直接显示全部数据 if (query.isEmpty) { setState(() { offersList = List.from(originalOffersList); }); return; } List<Map> filteredResults = []; for (var item in originalOffersList) { // 先判断当前map是否包含"foodname"键,避免空指针 if (item.containsKey("foodname")) { // 统一转成小写,实现忽略大小写的模糊匹配 String foodName = item["foodname"].toLowerCase(); String searchQuery = query.toLowerCase(); // 判断食物名称是否包含搜索关键词 if (foodName.contains(searchQuery)) { filteredResults.add(item); } } } // 更新显示列表 setState(() { offersList = filteredResults; }); }
方式2:使用Dart的where方法(简洁优雅)
void filterOffers(String query) { if (query.isEmpty) { setState(() { offersList = List.from(originalOffersList); }); return; } // 使用where过滤,最后转成列表 final filtered = originalOffersList.where((item) { if (!item.containsKey("foodname")) return false; return item["foodname"].toLowerCase().contains(query.toLowerCase()); }).toList(); setState(() { offersList = filtered; }); }
第三步:在搜索栏中调用过滤方法
把过滤方法绑定到搜索输入框的onChanged回调即可:
TextField( onChanged: (inputValue) { filterOffers(inputValue); }, decoration: const InputDecoration( hintText: "搜索食物名称", prefixIcon: Icon(Icons.search), ), )
内容的提问来源于stack exchange,提问作者Thejani Saranaguptha
相关产品推荐
相关产品推荐

