Flutter搜索功能Bug:搜索Apple时重复显示结果
Flutter搜索结果重复问题解决
问题分析
你提到的重复显示问题确实出在searchList的处理逻辑上:每次输入框内容变化时,你直接在原searchList基础上添加/移除元素,但没有在每次搜索前清空列表。比如输入"Apple"的过程中,每输入一个字符(A→Ap→App→Apple)都会触发一次onChanged,每次都会把符合当前输入的水果重复添加到searchList里,最终导致重复条目。
另外还有两个小问题:
- 搜索默认是大小写敏感的,输入小写"apple"会搜不到结果
- 使用
searchList.remove(fruit)的逻辑存在隐患,如果列表里没有对应元素会报错,且这种方式效率较低
修复后的完整代码
修改onChanged的处理逻辑,每次搜索时重新生成结果列表,从根源避免重复:
import 'package:flutter/material.dart'; void main() => runApp(MyApp()); class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Demo', debugShowCheckedModeBanner: false, theme: ThemeData( primarySwatch: Colors.blue, ), home: MyHomePage(title: 'Demo'), ); } } class MyHomePage extends StatefulWidget { final String title; MyHomePage({Key key, @required this.title}) : super(key: key); @override _MyHomePageState createState() => _MyHomePageState(); } class _MyHomePageState extends State<MyHomePage> { // 搜索输入框控制器 final _searchController = TextEditingController(); List<Fruit> mainList = [ Fruit(name: 'Apple', imageUrl: 'https://images.pexels.com/photos/102104/pexels-photo-102104.jpeg'), Fruit(name: 'Banana', imageUrl: 'https://images.pexels.com/photos/5945848/pexels-photo-5945848.jpeg'), Fruit(name: 'Pineapple', imageUrl: 'https://images.pexels.com/photos/1071878/pexels-photo-1071878.jpeg'), Fruit(name: 'Mango', imageUrl: 'https://images.pexels.com/photos/918643/pexels-photo-918643.jpeg'), ]; List<Fruit> searchList = []; @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text(widget.title), ), body: Column( children: [ Container( width: MediaQuery.of(context).size.width, height: 60.0, child: TextFormField( controller: _searchController, onChanged: (text){ setState((){ final query = text.trim().toLowerCase(); if(query.isNotEmpty){ // 每次搜索重新生成结果列表,彻底避免重复 searchList = mainList.where((fruit) { return fruit.name.toLowerCase().contains(query); }).toList(); }else{ searchList.clear(); } }); } ), ), Expanded( child: _searchController.text.isEmpty ? GridView.count( crossAxisCount: 2, children: mainList.map((fruit)=> CardWidget(fruit: fruit)).toList(), ) :GridView.count( crossAxisCount: 2, children: searchList.map((searchedFruit)=>CardWidget(fruit: searchedFruit)).toList() ), ), ], ), ); } } class Fruit{ final String imageUrl; final String name; Fruit({this.imageUrl, this.name}); } // 水果卡片组件 class CardWidget extends StatefulWidget{ final Fruit fruit; CardWidget({this.fruit}); @override _CardWidgetState createState()=> _CardWidgetState(); } class _CardWidgetState extends State<CardWidget>{ @override Widget build(BuildContext context){ return Container( width: 100.0, height: 140.0, child: Column( children:[ Image(image: NetworkImage(widget.fruit.imageUrl)), SizedBox(height: 10.0), Text(widget.fruit.name), ] ) ); } }
核心修改说明
- 用
where方法重新生成搜索结果列表,替代原有的循环添加/移除逻辑,从根源避免重复条目 - 将搜索关键词和水果名称统一转成小写,实现大小写不敏感搜索,优化用户体验
- 增加
trim()处理输入内容,避免首尾空格导致的无效搜索
内容的提问来源于stack exchange,提问作者tantan
相关产品推荐
相关产品推荐

