Flutter中Future<List<dynamic>?>列表显示与搜索重置问题
问题分析与解决方案
核心问题1:初始列表不显示/搜索功能失效
你当前的代码存在两个矛盾点:
- 仅给
allCandiesTypes赋值时,candyTypes初始为空,导致列表无数据显示; - 直接在
FutureBuilder的builder方法中给candyTypes赋值时,每次组件重建(比如搜索触发setState)都会重新执行这段赋值逻辑,覆盖搜索后的过滤结果,导致搜索失效。
解决思路:把列表初始化逻辑从FutureBuilder的builder中移出,改用Future.then在数据加载完成后通过setState更新状态,避免每次组件重建都重置candyTypes。
修改CandyTypeSearchViewState的initState方法:
@override void initState() { super.initState(); // 在Future完成后初始化列表,避免builder重复赋值 _candyTypes = viewModel.displayCandyTypeList().then((data) { if (mounted) { setState(() { allCandiesTypes = convertList(data); candyTypes = List.from(allCandiesTypes); // 初始显示全部数据 }); } }); }
修改candyTypeList的FutureBuilder逻辑,移除内部的列表赋值代码:
Widget candyTypeList() => FutureBuilder( future: _candyTypes, builder: (context, snapshot) { // 加载中/无数据状态 if (snapshot.connectionState == ConnectionState.waiting || !snapshot.hasData) { return const Loader(loaderWidth: 30, loaderHeight: 30); } // 错误状态 if (snapshot.hasError) { return ErrorText(errorMessage: snapshot.error.toString()); } // 数据已加载完成,直接使用已初始化的candyTypes return ListView.builder( itemCount: candyTypes.length, itemBuilder: (context, index) { final candyType = candyTypes[index]; return Column( children: [ ListTile( title: Padding( padding: ThemeSize.paddingSymmetric(s, s), child: Text( candyType.type!.toUpperCase(), style: TextStyle( color: ThemeColor.primary, fontSize: ThemeSize.text(l), ), ), ), onTap: () { Keyboard.sendFilterToFilterMenu(context, candyType.type!); }, ), const Divider(height: 1, color: ThemeColor.borderGrey), ], ); }, ); }, );
核心问题2:点击清除按钮无法重置列表
当前FilterSearchBar的清除按钮仅清空输入框,未通知父组件重置列表,需要新增回调实现该功能。
步骤1:修改FilterSearchBar,添加清除回调
class FilterSearchBar extends StatefulWidget { final String filterType; final TextEditingController searchController; final TextInputType keyboard; final ValueChanged<String>? onChanged; final VoidCallback? onClear; // 新增清除回调 const FilterSearchBar({ Key? key, required this.filterType, required this.searchController, required this.keyboard, this.onChanged, this.onClear, // 新增参数 }) : super(key: key); @override State<FilterSearchBar> createState() => _FilterSearchBarState(); } class _FilterSearchBarState extends State<FilterSearchBar> { bool showClearButton = false; @override void initState() { widget.searchController.addListener(() { setState(() { showClearButton = widget.searchController.text.isNotEmpty; }); }); super.initState(); } @override void dispose() { widget.searchController.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return TextFormField( keyboardType: widget.keyboard, controller: widget.searchController, onChanged: widget.onChanged, decoration: InputDecoration( border: const OutlineInputBorder( borderRadius: BorderRadius.all(Radius.circular(90.0)), borderSide: BorderSide( color: ThemeColor.white, ) ), prefixIcon: const Icon( Icons.search_rounded, color: ThemeColor.gray600, ), hintStyle: TextStyle( color: ThemeColor.black, fontSize: ThemeSize.text(m), fontWeight: FontWeight.normal, ), suffixIcon: showClearButton ? IconButton( onPressed: clearSearchBar, icon: const Icon( Icons.close_outlined, color: ThemeColor.gray500, ), ) : null, filled: true, fillColor: ThemeColor.white, hintText: widget.filterType, ), ); } void clearSearchBar() { widget.searchController.clear(); widget.onClear?.call(); // 触发清除回调 } }
步骤2:在CandyTypeSearchView中绑定清除回调
FilterSearchBar( filterType: context.translation.searchCandy, searchController: searchController, keyboard: TextInputType.text, onChanged: searchCandyType, onClear: () { // 绑定清除逻辑 setState(() { candyTypes = List.from(allCandiesTypes); }); }, )
额外优化:处理搜索框为空的情况
修改searchCandyType方法,当输入为空时自动重置列表:
void searchCandyType(String query) { if (query.isEmpty) { setState(() { candyTypes = List.from(allCandiesTypes); }); return; } suggestions = allCandiesTypes.where((candyType) { final candyTypeName = candyType.type!.toUpperCase().startsWith(query.toUpperCase()); return candyTypeName; }).toList(); setState(() => candyTypes = suggestions.isEmpty ? allCandiesTypes : suggestions); }
内容的提问来源于stack exchange,提问作者Seth
相关产品推荐
相关产品推荐

