You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 07:55:20