Firestore用户文档变更时如何自动更新Provider中的用户数据
解决方案
你可以将Firestore文档的实时订阅直接放在全局UserService中持有,无需绑定到具体页面生命周期,即可实现全应用范围内的用户数据自动同步,修改后的实现代码如下:
import 'dart:async'; import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:flutter/foundation.dart'; class UserService extends ChangeNotifier { final CollectionReference usersCollection = FirebaseFirestore.instance.collection('users'); late User _currentUser; User get currentUser => _currentUser; // 持有用户文档的监听订阅 StreamSubscription<DocumentSnapshot>? _userSubscription; // 开启用户文档实时监听,用户登录成功拿到uid后调用即可 void startListeningUser(String uid) { // 切换用户时先取消之前的订阅,避免数据串扰 _userSubscription?.cancel(); _userSubscription = usersCollection.doc(uid).snapshots().listen((snapshot) { if (snapshot.exists) { _currentUser = User.fromMap(snapshot.data()! as Map<String, dynamic>); if (kDebugMode) { print("nb lives : ${_currentUser.nbLives}"); } notifyListeners(); } }); } // 原有一次性获取用户的方法可保留,按需使用 Future<User> getUser(String uid) async { var userData = await usersCollection.doc(uid).get(); User user = User.fromMap(userData.data()!); _currentUser = user; notifyListeners(); return user; } // 用户登出时主动调用,释放资源避免内存泄漏 void disposeListener() { _userSubscription?.cancel(); _userSubscription = null; } // 重写dispose方法兜底释放资源 @override void dispose() { disposeListener(); super.dispose(); } }
实现说明
- 核心逻辑是将Stream订阅从页面迁移到全局的
UserService实例中,只要UserService没有被销毁,订阅就会持续生效,应用退到后台也能正常接收Firestore的变更推送 - 你之前的页面级Stream方案失效的原因是订阅和页面生命周期绑定,页面销毁时订阅也被同步取消,改为全局持有后就解决了该问题
注意事项
- 所有需要展示用户数据的页面,使用
Provider的Consumer/Selector监听UserService的currentUser,数据变更时会自动刷新UI - 可根据业务需求补充快照不存在、网络异常等场景的错误处理逻辑
内容的提问来源于stack exchange,提问作者Pierre
相关产品推荐
相关产品推荐

