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

Flutter搜索页第二个FutureBuilder异常,搜索时快照混淆问题

问题解决:搜索用户时快照复用导致字段不存在错误

问题根源

切换isShowUsers状态时,两个FutureBuilder属于同一Widget类型,Flutter的Element复用机制会让它们共享旧的快照数据。搜索用户时,新的用户查询请求还未返回,代码仍在使用之前帖子查询的快照,而帖子文档中没有photoUrl字段,因此抛出错误。

修复方案

给两个FutureBuilder设置唯一Key阻止Element复用,让它们各自维护独立的快照状态;同时优化Future创建逻辑,避免每次build重复发起请求。

修复后的代码

import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart';
import 'package:instagram_flutter/utils/colors.dart';

class SearchScreen extends StatefulWidget {
  const SearchScreen({super.key});

  @override
  State<SearchScreen> createState() => _SearchScreenState();
}

class _SearchScreenState extends State<SearchScreen> {
  final TextEditingController searchController = TextEditingController();
  bool isShowUsers = false;
  // 存储查询Future,避免重复发起请求
  Future<QuerySnapshot>? _usersFuture;
  Future<QuerySnapshot>? _postsFuture;

  @override
  void initState() {
    super.initState();
    // 初始化时加载帖子数据
    _postsFuture = FirebaseFirestore.instance.collection('posts').get();
  }

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: mobileBackgroundColor,
        title: TextFormField(
          controller: searchController,
          decoration: const InputDecoration(
            labelText: 'Search for a user',
          ),
          onFieldSubmitted: (String _) {
            setState(() {
              isShowUsers = true;
              // 提交搜索时发起用户查询
              _usersFuture = FirebaseFirestore.instance
                  .collection('users')
                  .where('username', isGreaterThanOrEqualTo: searchController.text)
                  .get();
            });
          },
        ),
      ),
      body: isShowUsers
          ? FutureBuilder(
              key: const Key('users_future_builder'),
              future: _usersFuture,
              builder: (context, snap) {
                if (!snap.hasData) {
                  return const Center(child: CircularProgressIndicator());
                }
                return ListView.builder(
                  itemCount: snap.data!.docs.length,
                  itemBuilder: (context, index) {
                    final userDoc = snap.data!.docs[index];
                    return ListTile(
                      leading: CircleAvatar(
                        backgroundImage: NetworkImage(userDoc['photoUrl']),
                      ),
                      title: Text(userDoc['username']),
                    );
                  },
                );
              },
            )
          : FutureBuilder(
              key: const Key('posts_future_builder'),
              future: _postsFuture,
              builder: (context, snapshot) {
                if (!snapshot.hasData) {
                  return const Center(child: CircularProgressIndicator());
                }
                return MasonryGridView.count(
                  crossAxisCount: 3,
                  itemCount: snapshot.data!.docs.length,
                  itemBuilder: (context, index) {
                    final postDoc = snapshot.data!.docs[index];
                    return Image.network(postDoc['postUrl']);
                  },
                );
              },
            ),
    );
  }
}

关键修改点

  • 新增_usersFuture和_postsFuture变量,将查询请求的Future存储在State中,避免每次build重复发起Firestore请求。
  • 给两个FutureBuilder设置唯一Key,确保Flutter不会复用它们的Element,各自管理独立的快照数据。
  • 仅在搜索提交时创建用户查询的Future,减少不必要的网络请求。

内容的提问来源于stack exchange,提问作者Nikhil Gupta

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 23:35:11