You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 15:27:00