Flutter Firebase文档引用调用异常:StreamProvider提前发起请求
问题分析与解决方案
核心问题
你的streamCompanies()方法存在异步时序错误:_userRef.get()是异步操作,通过then回调赋值thisUserCompany的逻辑会滞后于函数返回Stream的操作,导致返回的公司文档流基于未初始化或旧值的thisUserCompany,最终触发了错误的文档请求。
修复方案
1. 修正数据库服务的Stream生成逻辑
使用Dart的async*异步生成器,先等待用户文档获取完成拿到有效公司ID,再返回正确的公司文档实时流:
Stream<Companies> streamCompanies() async* { // 同步等待用户文档请求完成 final documentSnapshot = await _userRef.get(); if (documentSnapshot.exists) { final companyID = documentSnapshot.get('companyID'); debugPrint('Database Service => 已获取公司ID: $companyID'); // 拿到有效ID后,返回公司文档的实时监听流 yield* _database .collection('companies') .doc(companyID) .snapshots() .map((snapshot) => Companies.fromJson(snapshot.data() as Map<String, dynamic>)); } else { // 用户文档不存在时返回初始占位数据 yield Companies.initialData(); } }
2. Future模式报错的解决方式
如果想改用一次性获取数据的Future模式,不能继续使用StreamProvider,需替换为FutureProvider:
数据库服务新增Future方法
Future<Companies> fetchCompanies() async { final documentSnapshot = await _userRef.get(); if (documentSnapshot.exists) { final companyID = documentSnapshot.get('companyID'); final companySnapshot = await _database.collection('companies').doc(companyID).get(); return Companies.fromJson(companySnapshot.data() as Map<String, dynamic>); } return Companies.initialData(); }
替换为FutureProvider
MultiProvider(providers: [ FutureProvider<Companies?>( create: (context) => DatabaseService(uid: user.uid, companyID: user.companyID).fetchCompanies(), initialData: Companies.initialData(), ), ], child: const ProfileSelector())
3. 额外优化建议
- 避免使用全局变量
thisUserCompany存储公司ID,直接在异步流程中传递值,减少状态混乱 - 在
ProfileSelector中监听Companies数据时,可通过Consumer结合条件判断,避免初始占位数据的异常展示
内容的提问来源于stack exchange,提问作者Christopher Lowe
相关产品推荐
相关产品推荐

