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
相关产品推荐
相关产品推荐

