Flutter Firestore使用StreamBuilder获取到非当前用户数据如何解决
问题根因与修复方案
核心问题定位
- 你当前的UID是一次性静态获取的:代码中
final uid = _auth.currentUser!.uid;只会在变量初始化时读取一次当前登录用户的ID,后续切换账号登录/登出操作不会触发这个值更新,导致一直用首次获取的UID查询数据,自然返回的是其他账号的资料。 - 没有监听FirebaseAuth的登录状态变化,无法在用户切换时自动更新查询的数据源。
- 缺少空安全校验,当登录状态异常时
data!强制取值会触发崩溃。 - 重复创建多个StreamBuilder监听同一个流,属于不必要的性能浪费。
修复步骤
1. 改造为动态监听登录状态,动态生成查询流
不要提前写死UID和Firestore流,改为先监听用户登录状态,再根据当前登录用户动态生成对应的Profile查询流,示例代码如下:
// 首先引入FirebaseAuth实例 final FirebaseAuth _auth = FirebaseAuth.instance; @override Widget build(BuildContext context) { // 嵌套两层StreamBuilder,第一层监听登录状态变化 return StreamBuilder<User?>( stream: _auth.authStateChanges(), builder: (context, authSnapshot) { // 未登录状态处理 if (!authSnapshot.hasData) { return const Center(child: Text('请先登录')); } // 获取当前登录用户的UID,用户切换时会自动更新 final String currentUid = authSnapshot.data!.uid; // 动态生成对应当前用户的Profile查询流 final Stream<DocumentSnapshot<Map<String, dynamic>>> profileStream = FirebaseFirestore .instance .collection('users') .doc(currentUid) .collection('Profile') .doc('Personal details') .snapshots(); // 第二层监听Profile数据变化,只用一个StreamBuilder获取所有字段即可 return StreamBuilder<DocumentSnapshot<Map<String, dynamic>>>( stream: profileStream, builder: (context, profileSnapshot) { if (profileSnapshot.hasError) { return const Text('数据加载失败'); } if (profileSnapshot.connectionState == ConnectionState.waiting) { return const CircularProgressIndicator(); } // 空数据校验 if (!profileSnapshot.hasData || !profileSnapshot.data!.exists) { return const Text('未找到用户资料'); } final profileData = profileSnapshot.data!.data()!; // 你的原有UI布局 return Column( children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ const Text('First name'), const SizedBox(width: 40), Text(profileData['First name'] ?? ''), ], ), const Divider(color: Colors.black), const SizedBox(height: 10), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ const Text('Last name'), const SizedBox(width: 40), Text(profileData['Last name'] ?? '', style: boldFont), ], ), // 其余UI保持不变 ], ); }, ); }, ); }
2. 新增Firestore安全规则(强制数据隔离,必加)
在Firebase控制台的Firestore安全规则中添加如下配置,从服务端层面禁止用户访问其他账号的数据,就算前端代码出错也不会泄露他人信息:
rules_version = '2'; service cloud.firestore { match /databases/{database}/documents { match /users/{userId}/{document=**} { allow read, write: if request.auth != null && request.auth.uid == userId; } } }
内容的提问来源于stack exchange,提问作者reeco
相关产品推荐
相关产品推荐

