Flutter FutureBuilder的snapshot无数据仅热重载后正常问题排查
问题根因
- 核心原因是你在
FireBaseHandler的实例化阶段就初始化了myUser属性,首次登录成功后跳转到此页面时,FirebaseAuth.instance.currentUser还未完成本地状态同步,此时拿到的是null。后续调用getUserData时访问myUser.uid直接抛出空异常,逻辑走到catch块只打印了日志,没有返回任何有效值,Future完成后没有有效数据,所以userDataSnapshot.hasData始终为false。
热重载时页面重新构建,此时Firebase Auth的本地状态已经同步完成,currentUser有有效值,所以能正常拉取数据。 - 次要问题:
getUserData方法没有声明返回类型,catch异常后也没有返回null或者其他兜底值,异常发生后Future的返回值为空,无法触发hasData判断。- 你将
FireBaseHandler handler = FireBaseHandler();的初始化逻辑放在了build方法内,每次页面重绘都会创建新的实例、发起新的请求,虽然不是本次问题的直接诱因,但属于不规范写法。 - async/await和.then链式调用混用,逻辑不清晰。
修复方案
1. 调整FireBaseHandler实现,把currentUser的获取放到请求方法内
/// Helper Class class UserManager { static Map<String, dynamic>? userdata = null; } class FireBaseHandler { final CollectionReference usersCol = FirebaseFirestore.instance.collection('users'); /// fetch UserData Future<Map<String, dynamic>?> getUserData() async { try { // 把currentUser的获取移到方法内部,保证取到的是最新状态 final myUser = FirebaseAuth.instance.currentUser; if (myUser == null) { return null; } final value = await usersCol.doc(myUser.uid).get(); UserManager.userdata = value.data() as Map<String, dynamic>?; return UserManager.userdata; } catch (e) { print(e.toString()); // 异常时也返回null,保证Future有返回值 return null; } } }
2. 调整FutureBuilder使用方式,将Future初始化放到initState中
避免build方法重复创建请求实例,同时补充异常、加载完成状态判断:
class YourEntryPage extends StatefulWidget { const YourEntryPage({super.key}); @override State<YourEntryPage> createState() => _YourEntryPageState(); } class _YourEntryPageState extends State<YourEntryPage> { late Future<Map<String, dynamic>?> _userDataFuture; final FireBaseHandler handler = FireBaseHandler(); @override void initState() { super.initState(); _userDataFuture = handler.getUserData(); } @override Widget build(BuildContext context) { return FutureBuilder( future: _userDataFuture, builder: (context, userDataSnapshot) { // 补充错误状态处理 if (userDataSnapshot.hasError) { return Scaffold( body: Center(child: Text('加载失败,请重试')), ); } if (userDataSnapshot.connectionState == ConnectionState.done) { if (userDataSnapshot.data != null) { print(UserManager.userdata); return HomeScreen(); } else { return Scaffold( body: Center(child: Text('用户数据不存在')), ); } } else { return Scaffold( body: Center( child: CircularProgressIndicator(), ), ); } }, ); } }
内容的提问来源于stack exchange,提问作者Dalon
相关产品推荐
相关产品推荐

