使用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 错误 - 如何修复? [关闭]
Flutter - Provider - 如何根据 Provider 的值更改 UI?
如果您的名称包含非英语字符,请使用gyp for windows安装Fir npm。
如何解决 NullInjectorError: No provider for HttpClient! Ionic 4(Angular 8)中的问题