如何使用SearchBar组件筛选Flutter中的Future<List<Room>>数据
解决方案:在Flutter Web中实现游戏房间的实时筛选
核心思路是先获取并存储所有房间数据到本地状态,再基于搜索文本对本地数据进行筛选,避免重复调用API,同时解决无法直接筛选Future的问题。
修改步骤:
调整状态变量
- 移除原来的
Future<List<Room>>? gameRooms,换成三个状态变量:_allRooms:存储从API获取的所有房间,仅在初始化时赋值一次_filteredRooms:存储筛选后的房间,用于UI展示_isLoading:标记数据是否正在加载
- 移除原来的
重构数据获取逻辑
- 新增
_fetchGameRooms方法,调用API后将数据存入_allRooms,并初始化_filteredRooms,同时更新加载状态
- 新增
实现筛选逻辑
- 在
filterRoom方法中,根据搜索文本过滤_allRooms,将结果赋值给_filteredRooms并触发UI更新 - 加入大小写不敏感的匹配,提升用户体验
- 在
更新UI部分
- 绑定
SearchBar的onChanged到filterRoom方法 - 替换原来的
FutureBuilder,通过_isLoading判断展示加载状态或筛选后的房间列表
- 绑定
修改后的完整代码:
import 'package:boardhub/entities/room.dart'; import 'package:boardhub/routes/dashboard/components/room_card.dart'; import 'package:flutter/material.dart'; class Dashboard extends Stateful Widget { const Dashboard({super.key}); @override State<Dashboard> createState() => _DashboardState(); } class _DashboardState extends State<Dashboard> { List<Room> _allRooms = []; List<Room> _filteredRooms = []; bool _isLoading = true; Future<List<Room>> getGameRooms() async { await Future.delayed(const Duration(seconds: 3)); return List<Room>.generate(48, (index) => Room( gameName: "Sala de jogo $index", gameAddress: "Endereço $index", gameDate: DateTime.now() )); } @override void initState() { super.initState(); _fetchGameRooms(); } Future<void> _fetchGameRooms() async { final rooms = await getGameRooms(); setState(() { _allRooms = rooms; _filteredRooms = rooms; _isLoading = false; }); } void filterRoom(String filterText){ setState(() { if(filterText.trim().isEmpty){ _filteredRooms = _allRooms; } else { final lowerCaseFilter = filterText.toLowerCase(); _filteredRooms = _allRooms.where((room) => room.gameName.toLowerCase().contains(lowerCaseFilter) ).toList(); } }); } @override Widget build(BuildContext context) { return Column( children: [ SearchBar( leading: const Icon(Icons.search), hintText: "Dixit, Monopoly, Zombicide...", onChanged: filterRoom, ), _isLoading ? const CircularProgressIndicator() : Expanded( child: SingleChildScrollView( child: Wrap( spacing: 10, runSpacing: 10, children: [ const IconButton(onPressed: (){}, icon: Icon(Icons.abc)), for(Room room in _filteredRooms) RoomCard(room: room) ] ), ), ) ], ); } }
关键说明:
- 避免重复API调用:
_allRooms仅在初始化时通过_fetchGameRooms赋值一次,后续筛选完全基于本地数据 - 实时筛选:每次搜索文本变化时,通过
setState更新_filteredRooms,触发UI重新渲染 - 大小写不敏感匹配:将搜索文本和房间名称都转为小写后再判断包含关系,让筛选更友好
内容的提问来源于stack exchange,提问作者gaudiot
相关产品推荐
相关产品推荐

