Flutter中Firestore数据首次不显示及重复加载问题求助
问题描述
我是Dart编程新手,正在开发基于Firebase后端的基础App,实现认证功能与Firestore的CRUD操作。认证和新用户创建已成功,但使用FutureBuilder读取Firestore时遇问题:
- 首页(认证后跳转页面)首次启动不显示内容
- 热重载后可显示数据,但多次热重载会出现重复内容,页面累加所有请求的内容展示
首页文件
import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:firebase_auth/firebase_auth.dart'; import 'package:firebase_project_1/screens/home/read_data.dart'; import 'package:flutter/material.dart'; class Home extends StatefulWidget { const Home({super.key}); @override State<Home> createState() => _HomeState(); } class _HomeState extends State<Home> { final user = FirebaseAuth.instance.currentUser!; // 存储所有文档ID的列表 List<String> documentIDs = []; Future getDocIDs() async { await FirebaseFirestore.instance.collection('Users').get().then( (snapshot) => snapshot.docs.forEach( (document) { print(document.reference); documentIDs.add(document.reference.id); }, ), ); } @override void initState() { getDocIDs(); super.initState(); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( backgroundColor: Colors.deepPurple, title: Center( child: Text( textAlign: TextAlign.center, 'Display dashboard', style: TextStyle( fontSize: 30, color: Colors.tealAccent.shade400, ), ), ), actions: [ GestureDetector( onTap: () { FirebaseAuth.instance.signOut(); }, child: const Padding( padding: EdgeInsets.symmetric(horizontal: 10.0), child: Icon( Icons.logout_sharp, ), ), ) ], ), backgroundColor: Colors.deepPurple.shade200, body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.center, children: [ Expanded( child: FutureBuilder<Object>( builder: (context, index) { future: getDocIDs(); return ListView.builder( itemCount: documentIDs.length, itemBuilder: (context, index) { return ListTile( title: ReadData(docIDs: documentIDs[index]), ); }, ); }, ), ), ], ), ), ); } }
读数据文件
import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:flutter/material.dart'; class ReadData extends StatelessWidget { const ReadData({required this.docIDs, super.key}); final String docIDs; @override Widget build (BuildContext context) { CollectionReference users = FirebaseFirestore.instance.collection('Users'); return FutureBuilder<DocumentSnapshot>( future: users.doc(docIDs).get(), builder: (context, snapshot) { if (snapshot.connectionState == ConnectionState.done) { Map<String, dynamic> data = snapshot.data!.data() as Map<String, dynamic>; return Text('name: ${data['name']}'); } return const Text('Loading......'); }, ); } }
解决方案
你的问题源于两个核心错误:FutureBuilder的误用,以及未清空列表导致重复数据累加。
1. 修复FutureBuilder的使用逻辑
你当前把future: getDocIDs()写在builder函数内部,会导致每次Widget重建(比如热重载)都重复触发数据请求,且FutureBuilder无法正确跟踪Future状态。正确做法是将Future实例保存在State变量中,避免重复执行。
2. 避免数据重复累加
每次调用getDocIDs()时,先清空documentIDs列表,否则每次请求都会往列表里追加新ID,导致内容重复。
修改后的首页代码
import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:firebase_auth/firebase_auth.dart'; import 'package:firebase_project_1/screens/home/read_data.dart'; import 'package:flutter/material.dart'; class Home extends StatefulWidget { const Home({super.key}); @override State<Home> createState() => _HomeState(); } class _HomeState extends State<Home> { final user = FirebaseAuth.instance.currentUser!; List<String> documentIDs = []; late Future<void> _docIDsFuture; // 保存Future实例,避免重复触发请求 Future getDocIDs() async { documentIDs.clear(); // 请求前清空列表 final snapshot = await FirebaseFirestore.instance.collection('Users').get(); for (var doc in snapshot.docs) { documentIDs.add(doc.id); } } @override void initState() { _docIDsFuture = getDocIDs(); // 初始化时保存Future super.initState(); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( backgroundColor: Colors.deepPurple, title: const Center( child: Text( 'Display dashboard', textAlign: TextAlign.center, style: TextStyle( fontSize: 30, color: Colors.tealAccent, ), ), ), actions: [ GestureDetector( onTap: () => FirebaseAuth.instance.signOut(), child: const Padding( padding: EdgeInsets.symmetric(horizontal: 10.0), child: Icon(Icons.logout_sharp), ), ) ], ), backgroundColor: Colors.deepPurple.shade200, body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.center, children: [ Expanded( child: FutureBuilder<void>( future: _docIDsFuture, // 使用预存的Future实例 builder: (context, snapshot) { if (snapshot.connectionState == ConnectionState.waiting) { return const Center(child: Text('Loading......')); } else if (snapshot.hasError) { return Center(child: Text('加载失败: ${snapshot.error}')); } else { return ListView.builder( itemCount: documentIDs.length, itemBuilder: (context, index) { return ListTile( title: ReadData(docIDs: documentIDs[index]), ); }, ); } }, ), ), ], ), ), ); } }
额外优化建议
- 可使用
StreamBuilder替代FutureBuilder,实时监听Firestore数据变化,数据更新时页面自动刷新。 - 在
ReadData组件中添加错误处理逻辑,避免snapshot.data为空时触发异常。
内容的提问来源于stack exchange,提问作者Sivagnanam Maheshwaran
相关产品推荐
相关产品推荐

