Flutter加载本地JSON数据后如何实现搜索栏查询过滤功能
核心问题排查
你的代码存在5个关键错误导致搜索逻辑失效:
- 数据源作用域错误:
newData是FutureBuilder内部的局部变量,外部过滤方法无法访问和修改 - 没有备份原始全量数据:直接修改展示用的数据源,会导致多次搜索后没有原始数据可用于过滤
- 匹配逻辑错误:遍历的
item是JSON对象而非字符串,直接调用contains()方法会报错,应该匹配对象内的NAME字段 - 赋值逻辑反向:过滤得到的结果没有赋值给展示用的列表,反而重新赋值了原始数据,相当于过滤没生效
- 语法错误:
setState回调内不能直接return值,应该在回调内修改状态变量
完整修正方案
1. 定义全局状态变量
在State类内声明两个成员变量,分别存储原始全量数据和用于渲染的展示数据:
class _YourPageState extends State<YourPage> { // 原始全量数据,永远不要修改该变量,仅作为搜索的基准数据源 List originalData = []; // 用于列表渲染的动态数据,搜索过滤时仅修改该变量 List displayData = []; @override void initState() { super.initState(); // 页面初始化时提前加载JSON数据 loadJsonData(); }
2. 调整JSON加载逻辑
把原来写在FutureBuilder内的加载逻辑抽到独立方法中,避免局部变量无法访问的问题:
Future<void> loadJsonData() async { String jsonContent = await DefaultAssetBundle.of(context).loadString('files/myfile.json'); setState(() { originalData = json.decode(jsonContent); // 初始状态展示全量数据 displayData = List.from(originalData); }); }
3. 修改列表渲染逻辑
直接用displayData渲染ListView,不需要再嵌套FutureBuilder:
@override Widget build(BuildContext context) { return Scaffold( // 搜索栏的onChanged回调直接调用filterSearchResults方法即可 body: displayData.isEmpty ? const Center(child: CircularProgressIndicator()) : ListView.builder( itemCount: displayData.length, itemBuilder: (BuildContext context, int index) { String word = displayData[index]['NAME']; // 保留你原来的列表项渲染逻辑即可 return ListTile(title: Text(word)); } ), ); }
4. 重写搜索过滤方法
filterSearchResults(String query) { // 搜索词为空时重置为全量数据 if (query.trim().isEmpty) { setState(() { displayData = List.from(originalData); }); return; } // 转换为小写实现大小写不敏感搜索,体验更友好 String lowerQuery = query.trim().toLowerCase(); setState(() { displayData = originalData.where((item) { String itemName = item['NAME'].toString().toLowerCase(); return itemName.contains(lowerQuery); }).toList(); }); }
注意:你原来的搜索栏组件需要把输入内容的回调绑定到filterSearchResults方法上即可生效
内容的提问来源于stack exchange,提问作者Lash
相关产品推荐
相关产品推荐

