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

Flutter应用切换Firebase用户后Stream仍获取旧用户数据问题

问题:切换Firebase用户后仍加载旧用户数据

开发Flutter应用时,登录用户A可正常获取对应集合数据,但退出A登录B/C后,当前用户已切换,却始终加载用户A的uid对应数据。尝试过重新加载用户、手动刷新令牌、退出所有Provider、清除路由栈等操作,均未解决。

关键信息

Firebase用户信息

  • 用户A信息:
User(displayName: User A, email: usera@gmail.com, isEmailVerified: false, isAnonymous: false, metadata: UserMetadata(creationTime: 2023-08-07 19:09:04.926Z, lastSignInTime: 2023-08-15 18:38:10.163Z), phoneNumber: null, photoURL: null, providerData, [UserInfo(displayName: User A, email: usera@gmail.com, phoneNumber: null, photoURL: null, providerId: password, uid: usera@gmail.com)], refreshToken: null, tenantId: null, uid: iceESRpOmtaWWjeE1VTlMMrOAro1)
  • 用户B信息:
User(displayName: User B, email: userb@gmail.com, isEmailVerified: false, isAnonymous: false, metadata: UserMetadata(creationTime: 2023-08-07 19:09:04.926Z, lastSignInTime: 2023-08-15 18:38:10.163Z), phoneNumber: null, photoURL: null, providerData, [UserInfo(displayName: User B, email: userb@gmail.com, phoneNumber: null, photoURL: null, providerId: password, uid: usera@gmail.com)], refreshToken: null, tenantId: null, uid: 3xvFuzudBbWf1qy8L1otH2Ft0fy1)

集合数据

  • 用户A的集合数据:
PREVIOUS UserModel(uid: iceESRpOmtaWWjeE1VTlMMrOAro1, name: User A, email: usera@gmail.com, status: true, createdAt: 1691435312287, updatedAt: 1692124235394)
  • 切换用户后加载的集合数据:
CURRENT UserModel(uid: iceESRpOmtaWWjeE1VTlMMrOAro1, name: User A, email: usera@gmail.com, status: true, createdAt: 1691435312287, updatedAt: 1692124235394)

相关代码

MultiProvider中的StreamProvider

StreamProvider<UserModel?>(
          initialData: null,
          create: (_) => firestoreService.getUserStreamDetail(),
          updateShouldNotify: (p, c) {
            console.log('PREVIOUS $p, CURRENT $c');
            return true;
          },
        )

获取用户数据的函数

Stream<UserModel>? getUserStreamDetail() {
    try {
      if (user != null) {
        return firestoreReference.doc(user!.uid).snapshots().map((doc) {
          log('USER DATA ${doc.data()}');
          return UserModel.fromSnapshot(doc);
        });
      }
      return null;
    } on FirebaseException catch (e) {
      log('26 ERROR $e');
      ToastFunctions.showWarningToast(e.message ?? 'Something went wrong...');
      rethrow;
    } catch (e) {
      log('30 error $e');
      ToastFunctions.showWarningToast(e.toString());
      rethrow;
    }
  }

问题根源

  1. StreamProvider初始化后不再更新:当前的StreamProvider在创建时仅调用一次getUserStreamDetail(),获取的是用户A对应的Firestore流。后续用户切换时,create方法不会重新执行,导致流始终指向用户A的文档。
  2. 用户状态未联动监听:getUserStreamDetail()依赖的user变量可能是缓存的旧实例,没有监听Firebase Auth的用户状态变化,无法在用户切换时获取最新的用户uid。

解决方案

方案1:让StreamProvider依赖Auth用户流

修改StreamProvider,使其监听Firebase Auth的用户状态变化,当用户切换时自动重新获取对应Firestore流:

StreamProvider<UserModel?>(
  initialData: null,
  create: (_) => FirebaseAuth.instance.authStateChanges()
      .switchMap((firebaseUser) {
        if (firebaseUser == null) {
          return Stream.value(null);
        }
        // 每次用户变化时,返回新的Firestore流
        return firestoreReference.doc(firebaseUser.uid).snapshots()
            .map((doc) => UserModel.fromSnapshot(doc));
      }),
  updateShouldNotify: (p, c) => true,
)

方案2:修改getUserStreamDetail方法,监听用户状态

如果需要保留firestoreService的封装,可修改getUserStreamDetail(),让它内部监听Auth用户流:

Stream<UserModel?> getUserStreamDetail() {
  return FirebaseAuth.instance.authStateChanges().switchMap((firebaseUser) {
    if (firebaseUser == null) {
      return Stream.value(null);
    }
    try {
      return firestoreReference.doc(firebaseUser.uid).snapshots().map((doc) {
        log('USER DATA ${doc.data()}');
        return UserModel.fromSnapshot(doc);
      });
    } on FirebaseException catch (e) {
      log('26 ERROR $e');
      ToastFunctions.showWarningToast(e.message ?? 'Something went wrong...');
      rethrow;
    } catch (e) {
      log('30 error $e');
      ToastFunctions.showWarningToast(e.toString());
      rethrow;
    }
  });
}

然后更新StreamProvider的create方法:

StreamProvider<UserModel?>(
  initialData: null,
  create: (_) => firestoreService.getUserStreamDetail(),
  updateShouldNotify: (p, c) => true,
)

方案3:确保user变量实时更新

如果firestoreService中的user变量是手动维护的,需确保在用户登录/退出时同步更新该变量,并且在getUserStreamDetail()中每次都获取最新的user。但这种方式不如直接监听Auth流可靠,因为手动维护容易出现同步问题。

内容的提问来源于stack exchange,提问作者Ayub Alam

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 00:22:37