[英]Flutter Firebase: How to remove firebase listener when using stream builder?
[英]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.