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

Flutter列表搜索功能求助:模糊搜索结果无法在ListView更新

问题分析与解决方案

核心问题有两个:

  1. 你在StreamBuilder的builder方法里定义的data是局部变量,调用setState修改它根本不会触发UI重建——StreamBuilder只会在Firestore的快照更新时重新执行builder,搜索输入的变化不会触发这个流程。
  2. 直接修改原始数据会导致后续搜索丢失全量数据源,没法恢复到初始状态。

修复步骤

  1. 在你的State类里添加两个成员变量,分别存全量数据和过滤后的数据:
List<DebrisPeopleModel> _allDebrisPeople = [];
List<DebrisPeopleModel> _filteredDebrisPeople = [];
  1. 修改StreamBuilder的逻辑,拿到Firestore数据后初始化这两个变量:
StreamBuilder(
  stream: db.collection("DebrisPeoples").snapshots(),
  builder: (context, snapshot) {
    if (!snapshot.hasData) {
      return const Center(child: CircularProgressIndicator());
    } else {
      // 初始化全量数据
      _allDebrisPeople = snapshot.data!.docs
          .map((e) => DebrisPeopleModel.fromDocument(e))
          .toList();
      // 首次加载时过滤数据等于全量数据
      if (_filteredDebrisPeople.isEmpty) {
        _filteredDebrisPeople = List.from(_allDebrisPeople);
      }
      return Column(
        children: [
          const SizedBox(height: 10),
          SizedBox(
            width: MediaQuery.of(context).size.width * 0.95,
            child: TextFormField(
              decoration: InputDecoration(
                prefixIcon: const Icon(Icons.search),
                contentPadding: const EdgeInsets.only(),
                border: OutlineInputBorder(
                  borderRadius: BorderRadius.circular(30),
                ),
              ),
              onChanged: (value) {
                // 基于全量数据做模糊搜索
                final filteredList = _allDebrisPeople.where((element) {
                  // 处理nameSurname为null的情况,避免崩溃
                  if (element.nameSurname == null) return false;
                  return element.nameSurname!.toLowerCase().contains(value.toLowerCase());
                }).toList();
                setState(() {
                  _filteredDebrisPeople = filteredList;
                });
              },
            ),
          ),
          SizedBox(
            width: double.infinity,
            height: MediaQuery.of(context).size.height * 0.8,
            child: ListView.builder(
              physics: const BouncingScrollPhysics(),
              // 改用过滤后的数据长度
              itemCount: _filteredDebrisPeople.length,
              itemBuilder: (context, index) {
                final item = _filteredDebrisPeople[index];
                return Card(
                  child: ListTile(
                    leading: Icon(
                      item.personSize == 1 ? Icons.person : Icons.people,
                    ),
                    title: Text(item.nameSurname.toString()),
                    subtitle: Text("${item.city} / ${item.district}"),
                    trailing: IconButton(
                      icon: const Icon(Icons.info),
                      onPressed: () {
                        Get.to(const UnderRublePeopleDetailPage(), arguments: item);
                      },
                    ),
                  ),
                );
              },
            ),
          ),
        ],
      );
    }
  },
),

关键修改点

  • 分离全量数据和过滤数据,保证每次搜索都有完整的数据源
  • 使用setState更新过滤后的数据,触发ListView的UI重建
  • 增加了nameSurname的空判断,避免空指针异常
  • ListView的itemCount和数据来源改为过滤后的列表

内容的提问来源于stack exchange,提问作者Emir Bolat

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 04:31:01