Flutter本地JSON搜索栏实现问题:数据无法显示排查
Flutter本地JSON搜索后数据不显示问题排查与修复
以下是你的代码中存在的核心问题及修复方案:
问题点分析
- 未正确初始化数据源:
initState中调用ReadJsonData但未将返回结果赋值给_userDetails,同时FutureBuilder每次build都会重新加载JSON,但同样没把数据存入_userDetails,导致原始数据始终为空。 - 搜索结果列表数据源错误:搜索结果的ListView使用了
_userDetails[index],而非过滤后的_searchResult[index],且未设置itemCount,无法正确渲染搜索结果。 - UI未触发更新:
onSearchTextChanged中修改_searchResult后未调用setState,导致UI不会刷新显示过滤结果。 - 条件判断逻辑缺陷:当输入搜索文本但无匹配结果时,会显示空列表,没有处理无结果的提示。
修复后的完整代码
import 'dart:convert'; import 'package:falamhymns/models/sawnawk_model.dart'; import 'package:falamhymns/sub_screens/detail_screen.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart' as rootBundle; class SawnawkScreen extends StatefulWidget { SawnawkScreen({Key? key}) : super(key: key); @override State<SawnawkScreen> createState() => _SawnawkScreenState(); } class _SawnawkScreenState extends State<SawnawkScreen> { final TextEditingController controller = TextEditingController(); List<SawnAwkModel> _searchResult = []; List<SawnAwkModel> _userDetails = []; bool _isLoading = true; @override void initState() { super.initState(); _loadJsonData(); } // 加载JSON数据并赋值给_userDetails Future<void> _loadJsonData() async { final data = await ReadJsonData(); setState(() { _userDetails = data; _isLoading = false; }); } void onSearchTextChanged(String text) { _searchResult.clear(); if (text.isEmpty) { setState(() {}); return; } // 遍历原始数据过滤匹配项 for (final item in _userDetails) { if (item.titleFalam.contains(text) || item.titleEnglish.contains(text)) { _searchResult.add(item); } } setState(() {}); // 更新UI } @override Widget build(BuildContext context) { return Scaffold( body: _isLoading ? const Center(child: CircularProgressIndicator()) // 加载状态提示 : Column( children: <Widget>[ Container( color: Colors.blue, child: Padding( padding: const EdgeInsets.all(8.0), child: Card( child: ListTile( leading: const Icon(Icons.search), title: TextField( controller: controller, decoration: const InputDecoration( hintText: 'Search', border: InputBorder.none, ), onChanged: onSearchTextChanged, ), trailing: IconButton( icon: const Icon(Icons.cancel), onPressed: () { controller.clear(); onSearchTextChanged(''); }, ), ), ), ), ), Expanded( child: controller.text.isNotEmpty ? _searchResult.isNotEmpty ? ListView.builder( itemCount: _searchResult.length, itemBuilder: (context, index) { final item = _searchResult[index]; return Card( elevation: 5, margin: const EdgeInsets.symmetric( horizontal: 10, vertical: 6, ), child: InkWell( onTap: () { Navigator.push( context, MaterialPageRoute( builder: (context) => DetailScreen(item.pageNumber), ), ); }, child: Container( padding: const EdgeInsets.only(bottom: 8), child: Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, children: [ Padding( padding: const EdgeInsets.all(8), child: Text(item.titleFalam), ), Padding( padding: const EdgeInsets.all(8), child: Text(item.titleEnglish), ), ], ), ), ), ); }, ) : const Center(child: Text("No results found")) // 无结果提示 : ListView.builder( itemCount: _userDetails.length, itemBuilder: (context, index) { final item = _userDetails[index]; return Card( child: ListTile( title: Text(item.titleFalam), onTap: () { Navigator.push( context, MaterialPageRoute( builder: (context) => DetailScreen(item.pageNumber), ), ); }, ), ); }, ), ), ], ), ); } } Future<List<SawnAwkModel>> ReadJsonData() async { final jsondata = await rootBundle.rootBundle.loadString('data/sawnawk_data.json'); final list = json.decode(jsondata) as List<dynamic>; return list.map((e) => SawnAwkModel.fromJson(e)).toList(); }
关键修复说明
- 初始化数据:新增
_loadJsonData方法,将JSON加载结果赋值给_userDetails并更新加载状态,避免重复加载。 - 修正搜索数据源:搜索结果ListView使用
_searchResult作为数据源,并设置itemCount。 - 触发UI更新:在
onSearchTextChanged中修改_searchResult后调用setState,确保UI刷新。 - 完善状态处理:添加加载状态提示和无搜索结果提示,提升用户体验。
- 优化代码结构:移除冗余的
FutureBuilder,改用状态变量控制加载状态,避免不必要的重复调用。
内容的提问来源于stack exchange,提问作者aase movie
相关产品推荐
相关产品推荐

