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

Flutter中解决FutureBuilder+ListView搜索输入异常的方法

问题修复方案

核心问题分析

你的问题源于两个关键错误:

  1. 第一页FutureBuilder每次重建都会重新发起异步请求,导致第二页被反复实例化,输入状态丢失;
  2. 第二页动态替换appBarTitle为TextField,每次setState都会重建输入框,无法维持输入焦点与内容。

以下是针对性修复代码及说明:


第一页(数据获取页)修复

class firstPage extends StatefulWidget {
  @override
  _HomePageState createState() => _HomePageState();
}

class _HomePageState extends State<firstPage> {
  late Future<List<AllProductModel>> _productsFuture;

  @override
  void initState() {
    super.initState();
    // 仅在初始化时发起一次异步请求,避免重复加载
    _productsFuture = fetchYourProduct(Uids, NameUserContry);
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: kBackground,
      body: Center(
        child: Column(
          children: [
            Expanded(
              child: FutureBuilder<List<AllProductModel>>(
                future: _productsFuture, // 使用预初始化的Future变量
                builder: (context, snapshot) {
                  final ListDataDisplay = snapshot.data;

                  switch (snapshot.connectionState) {
                    case ConnectionState.waiting:
                      return const Center(child: CircularProgressIndicator());
                    default:
                      if (snapshot.hasError) {
                        return const Center(child: Text('Some error occurred!'));
                      } else if (ListDataDisplay == null) {
                        return const Center(child: Text('No data available'));
                      } else {
                        return UserPage(ListDataDisplay: ListDataDisplay);
                      }
                  }
                },
              ),
            )
          ],
        ),
      ),
    );
  }
}

修复说明

  • 将异步请求移至initState中执行,保存为成员变量_productsFuture,确保仅发起一次请求,避免组件重建时重复加载数据。

第二页(搜索列表页)修复

class UserPage extends StatefulWidget {
  final List<AllProductModel> ListDataDisplay;
  UserPage({Key? key, required this.ListDataDisplay}) : super(key: key);

  @override
  State<UserPage> createState() => _UserPageState();
}

class _UserPageState extends State<UserPage> {
  final TextEditingController searchController = TextEditingController();
  late List<AllProductModel> _filteredList;
  bool _isSearching = false;

  @override
  void initState() {
    super.initState();
    _filteredList = widget.ListDataDisplay;
    // 监听搜索框输入,实时过滤数据
    searchController.addListener(() {
      setState(() {
        final searchText = searchController.text.toLowerCase();
        _filteredList = widget.ListDataDisplay.where((product) {
          return product.name.toLowerCase().contains(searchText) ||
              product.coponId.toLowerCase().contains(searchText);
        }).toList();
      });
    });
  }

  @override
  void dispose() {
    searchController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        centerTitle: true,
        title: _isSearching
            ? TextField(
                controller: searchController,
                style: const TextStyle(color: Colors.black),
                decoration: const InputDecoration(
                  labelText: 'Name',
                  enabledBorder: UnderlineInputBorder(
                    borderSide: BorderSide(color: Colors.black),
                  ),
                ),
                autofocus: true,
              )
            : const Text("List"),
        backgroundColor: CustomColors.firebaseGrey,
        elevation: 1.5,
        actions: [
          IconButton(
            onPressed: () {
              setState(() {
                _isSearching = !_isSearching;
                if (!_isSearching) {
                  searchController.clear();
                  _filteredList = widget.ListDataDisplay;
                }
              });
            },
            icon: Icon(
              _isSearching ? Icons.close : Icons.search,
              color: CustomColors.firebaseNavy,
            ),
          ),
        ],
      ),
      body: ListView.builder(
        physics: const ScrollPhysics(),
        scrollDirection: Axis.vertical,
        shrinkWrap: true,
        itemCount: _filteredList.length,
        itemBuilder: (context, index) {
          final product = _filteredList[index];
          return Card(
            elevation: 1.5,
            child: Container(
              padding: const EdgeInsets.all(6),
              child: Row(
                children: [
                  Text(product.name),
                ],
              ),
            ),
          );
        },
      ),
    );
  }
}

修复说明

  1. 避免输入框重建:使用_isSearching状态变量控制标题栏显示内容,TextField始终为同一个实例,不会因setState丢失输入状态;
  2. 优化搜索逻辑:维护_filteredList变量,提前过滤数据,避免在itemBuilder中生成大量空容器,提升性能;
  3. 修正搜索判断:改为分别判断名称和coponId是否包含搜索内容,同时忽略大小写,提升搜索体验。

内容的提问来源于stack exchange,提问作者M Al

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 20:40:29