使用Provider for DI时如何根据Firebase Auth流修改Flutter Firebase Stream监听器?

Posted

技术标签:

【中文标题】使用Provider for DI时如何根据Firebase Auth流修改Flutter Firebase Stream监听器?【英文标题】:How to modify Flutter Firebase Stream listener based on Firebase Auth stream when using Provider for DI? 【发布时间】:2021-01-18 17:05:53 【问题描述】:

在我的带有状态管理提供程序的 Flutter Firebase 应用程序中,我有一个用于响应FirebaseAuth.instance.authStateChanges() 的流和一个单独的流,用于侦听uid 提供的登录uid 的我的应用程序相关元数据。

    return MultiProvider(
      providers: [

        // This returns a stream of firebase user auth events so my app can react to 
        // login, force logout, etc. 
        StreamProvider<fireauth.User>.value(
          value: FirebaseAuth.instance.authStateChanges(),
        ),
        
        // conditional on non-null FirebaseAuth User, I would like to register a Firestore listener 
        // for the provided userId.
        // For security purposes, if the authenticated uid changes, the listener should be dereigstered.
        // After logout, if a different user is logged in, the this stream should listen to that uid's doc.
        StreamProvider<MyUser>.value(
          value: FirebaseFirestore.instance.collection('users')
                   .doc(/* use the userId from firebaseAuth here! */)
                   .snapshots()
                   .map((ds) => MyUser.fromJson(ds.data()))
        ),

      ],
  );

我想我可以使用ProxyProvider 来允许MyUser 流依赖FirebaseAuth.User 流,但是一旦为uid 注册了MyUser 流,它似乎是不可变的。如何根据FirebaseAuth.User 的结果“重新加载”Firestore 流?

【问题讨论】:

您是要根据任何更改还是根据什么来重新加载?我问是因为您使用 'userChanges()' 方法可能会更好,因此它可以更新流而无需您重新加载它,如 firebase.flutter.dev/docs/auth/usage 所述 【参考方案1】:

遇到了同样的问题,但使用的是 Firebase 实时数据库。使用async 包我创建了一个StreamGroup。一个 StreamGroup。

创建流组: StreamGroup group = StreamGroup();

创建流变量: Stream streamvar;

使用此方案创建的函数:


    Stream<PlaceHolderClass> functionName(User user) async*
      if (user != null) 
          await for (var x in streamOfFirestoreDocuments) 
            yield PlaceHolderClass();
          
         else 
          yield PlaceHolderClass();
        
    

创建了一个初始化器:

我在哪里听过: FirebaseAuth.instance.authStateChanges() 并将其添加到group.add() 的组中, 还设置流变量并将其添加到组中: streamvar = functionName(FirebaseAuth.instance.currentUser); group.add(streamvar)

然后创建:

Stream<FirestoreDocuments> providerFunc()
  return group.stream.map((event) 
   if(isUserChangetest)
     
     group.remove(streamvar);
     streamvar = newStreamvar;
     group.add(newStreamvar)
     fetch = newFirestoreDocs;
     return fetch;
else
 return sth;


)



现在streamVar 始终持有对group 的最后一个firestore 流输入的引用。 从 Firestore 交换流,您可以同时收听 Firestore 和 Auth 的两种更改。 以防我错过了什么:


    class Wallet 
      static final Wallet _singleton = Wallet._internal();
      factory Wallet() 
        return _singleton;
      
      Wallet._internal();
      Stream coins;
      create() 
        Stream<CrossOver> signin = FirebaseAuth.instance
            .authStateChanges()
            .map((event) => CrossOver(user: event, isnum: false));
        group.add(signin);
        coins = replace(FirebaseAuth.instance.currentUser);
        group.add(coins);
      
    
      Stream<CrossOver> replace(User user) async* 
        if (user != null) 
          await for (var x in FirebaseDatabase.instance
              .reference()
              .child('users/' + user.uid + '/scans')
              .onValue) 
            yield CrossOver(coins: Coins.load(x.snapshot.value), isnum: true);
          
         else 
          yield CrossOver(coins: Coins.load(0), isnum: true);
        
      
    
      Stream<Coins> real() 
        return group.stream.map((event) 
          Coins val;
          if (event.isnum == true) 
            print('new money');
            val = event.coins;
          
          if (event.isnum == false) 
            Stream<CrossOver> nStream = replace(event.user);
            print('new user');
            group.remove(coins);
            coins = nStream;
            group.add(nStream);
            FirebaseDatabase.instance
                .reference()
                .child('users/' + event.user.uid + '/scans')
                .once()
                .then((value) => val = Coins.load(value.value));
          
          return val;
        );
      
    
      StreamGroup<CrossOver> group = StreamGroup();
    
    
    class Coins 
      int money;
      Coins(this.money);
      factory Coins.load(int i) 
        return Coins(i);
      
    
    
    class CrossOver 
      bool isnum;
      User user;
      Coins coins;
      CrossOver(this.user, this.coins, this.isnum);
    


【讨论】:

【参考方案2】:

我在 rxdart 中使用了 flatMap() 来合并和组合 auth 用户流和 firestore 用户流,以便生成的流同时侦听 auth 和 firestore 更改。

我在这里用代码写了一个更详细的答案:https://***.com/a/66234728/10394353

【讨论】:

以上是关于使用Provider for DI时如何根据Firebase Auth流修改Flutter Firebase Stream监听器?的主要内容,如果未能解决你的问题,请参考以下文章

Storybook 6 错误:ngrx no provider for Store 错误 - 如何修复? [关闭]

AngularJS 2 Provider

Flutter - Provider - 如何根据 Provider 的值更改 UI?

如果您的名称包含非英语字符,请使用gyp for windows安装Fir npm。

AngularJS入门

如何解决 NullInjectorError: No provider for HttpClient! Ionic 4(Angular 8)中的问题