繁体   English   中英

使用提供程序进行 DI 时,如何根据 Firebase Auth 流修改 Flutter Firebase Stream 侦听器?

[英]How to modify Flutter Firebase Stream listener based on Firebase Auth stream when using Provider for DI?

在带有用于状态管理的 Provider 的 Flutter Firebase 应用程序中,我有一个用于FirebaseAuth.instance.authStateChanges()的流和一个单独的流,用于侦听FirebaseAuth提供的登录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 流?

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

创建流StreamGroup group = 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});
    }


我在rxdart 中使用了flatMap()来合并和组合 auth 用户流和 firestore 用户流,因此生成的流可以监听 auth 和 firestore 的变化。

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM