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

Flutter:如何为FutureBuilder加载的ListView列表实现搜索筛选功能

实现方案

你当前的核心问题是没有对接口返回的员工数据集做本地过滤,同时每次输入触发setState都会重新请求Firebase接口,存在不必要的性能损耗。按以下步骤修改即可:

核心修改点

  • 新增两个List变量分别存储全量员工数据和筛选后的员工数据,避免重复请求接口
  • 搜索内容变化时,对全量数据做模糊匹配筛选,刷新筛选列表即可
  • 匹配逻辑默认支持姓名、部门、职位三个字段的大小写不敏感模糊搜索,可自行增减匹配字段

修改后完整代码

import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';
import 'directory_details_screen.dart';

class Directory extends StatefulWidget {
  @override
  _DirectoryState createState() => _DirectoryState();
}

class _DirectoryState extends State<Directory> {
  TextEditingController _searchController = TextEditingController();
  // 新增变量:存储全量员工数据、筛选后员工数据、加载状态
  List<Employee> _allEmployees = [];
  List<Employee> _filteredEmployees = [];
  bool _isLoading = true;

  Future getEmpData() async {
    var response = await http.get(Uri.parse('你的Firebase数据库地址'));
    var jsonData = jsonDecode(response.body);
    List<Employee> employees = [];
    for (var e in jsonData) {
      Employee employee = Employee(
          e["displayName"],
          e["department"],
          e["jobTitle"],
          e["mobilePhone"],
          e["workEmail"],
          e["photoUrl"],
          e["workPhoneExtension"]);
      employees.add(employee);
    }
    // 赋值全量数据和初始筛选数据
    _allEmployees = employees;
    _filteredEmployees = employees;
    setState(() {
      _isLoading = false;
    });
  }

  @override
  void initState() {
    super.initState();
    // 页面初始化时请求一次数据即可
    getEmpData();
    _searchController.addListener(_onSearchChanged);
  }

  @override
  void dispose() {
    _searchController.removeListener(_onSearchChanged);
    _searchController.dispose();
    super.dispose();
  }

  _onSearchChanged() {
    String searchKey = _searchController.text.toLowerCase();
    setState(() {
      if (searchKey.isEmpty) {
        // 搜索内容为空时展示全部数据
        _filteredEmployees = _allEmployees;
      } else {
        // 按匹配规则过滤,可自行增减匹配字段
        _filteredEmployees = _allEmployees.where((employee) {
          return employee.displayName.toLowerCase().contains(searchKey) ||
              employee.department.toLowerCase().contains(searchKey) ||
              employee.jobTitle.toLowerCase().contains(searchKey);
        }).toList();
      }
    });
  }

  Widget build(BuildContext context) {
    return Scaffold(
      body: Column(
        mainAxisSize: MainAxisSize.max,
        mainAxisAlignment: MainAxisAlignment.start,
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          SizedBox(height: 10),
          Padding(
            padding: const EdgeInsets.symmetric(horizontal: 15.0),
            child: TextField(
              controller: _searchController,
              decoration: InputDecoration(
                labelText: 'Search',
                suffixIcon: Icon(Icons.search),
              ),
            ),
          ),
          SizedBox(height: 10),
          Expanded(
            child: _isLoading
                ? Center(child: CircularProgressIndicator())
                : _filteredEmployees.isEmpty
                    ? Center(child: Text('未找到匹配的员工信息'))
                    : ListView.builder(
                        itemCount: _filteredEmployees.length,
                        itemBuilder: (context, i) {
                          Employee employee = _filteredEmployees[i];
                          return Card(
                            child: ListTile(
                              leading: CircleAvatar(
                                backgroundImage: NetworkImage(employee.photoUrl),
                              ),
                              isThreeLine: true,
                              title: Text(employee.displayName,
                                  style: TextStyle(fontWeight: FontWeight.bold)),
                              subtitle: Text("Department: " +
                                  employee.department +
                                  "\n" +
                                  "Title: " +
                                  employee.jobTitle),
                              onTap: () {
                                Navigator.of(context).push(MaterialPageRoute(
                                    builder: (context) => EmployeeDetails(
                                        employee: employee)));
                              },
                            ),
                          );
                        }),
          ),
        ],
      ),
    );
  }
}

class Employee {
  final String displayName,
      department,
      jobTitle,
      mobilePhone,
      workEmail,
      photoUrl,
      workPhoneExtension;
  Employee(this.displayName, this.department, this.jobTitle, this.mobilePhone,
      this.workEmail, this.photoUrl, this.workPhoneExtension);
}

额外说明

如果需要增加匹配字段(比如邮箱、手机号),只需要在_onSearchChanged的过滤逻辑里新增对应的判断条件即可。


内容的提问来源于stack exchange,提问作者Bryan S

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 14:06:06