我一直在尝试使用从我的认证Provider
获得的 uid 创建流到Firestore文档的流:
class AuthService {
...
static final provider = StreamProvider.autoDispose((ref) => FirebaseAuth.instance.onAuthStateChanged);
...
}
但是,我正努力根据auth StreamProvider
中的值来创建一个Provider
。
class User {
...
static final provider = StreamProvider((ref) {
final stream = ref.read(AuthService.provider);
// Returns AsyncValue<Stream<User>> instead of desired AsyncValue<User>
return stream.map((auth) => Service.user.stream(auth.uid));
});
...
}
我还尝试使用Computed
返回 uid 或流本身,但是您无法从Computed
读取Provider
(回想起来很有意义)。
This question是与此主题最相关的内容,但它与提供者(而不是Riverpod)打交道。
P.S。可以创建Riverpod标签吗?
编辑:
答案不太正确。 await for loop
仅触发一次,而侦听器捕获所有事件。
static final provider = StreamProvider((ref) async* {
final stream = ref.read(AuthService.provider);
print('userProvider init');
stream.listen((auth) {
print('LISTENED: ${auth?.uid}');
});
await for (final auth in stream) {
print('uid: ${auth?.uid}');
yield* Service.user.stream(auth?.uid);
}
});
此代码在登录时会产生以下内容:
userProvider init
LISTENED: <redacted UID>
uid: <redacted UID>
然后注销:
LISTENED: null
我也希望看到uid: null
,它将更新流,但是在发生更多的auth事件时,仅触发侦听器,而await for loop
不会捕获任何事件。
有趣的是,使用flutter检查器,auth提供程序发出的值永远不会更改,
AutoDisposeStreamProvider<FirebaseUser>#95f11: AsyncValue<FirebaseUser>.data(value: FirebaseUser(Instance of 'PlatformUser'))
通过登录/注销事件持续存在,这可以解释这种现象,但是我不确定该如何解决。
有什么想法吗?我已经坚持了一段时间,无法解决问题。
答案 0 :(得分:4)
问题是,您的提供商没有创建Stream<User>
,而是创建Stream<Stream<User>>
作为0.6.0-dev的一部分,您可以使用ref.watch
轻松组合流:
class User {
...
static final provider = StreamProvider((ref) {
final auth = ref.watch(AuthService.provider);
return Service.user.stream(auth.uid);
});
...
}
答案 1 :(得分:1)
我想通过说我只与Dart / Flutter一起工作了几个月来对此做个开头,所以请随时纠正我说的任何内容,然后我将更新答案。
经过反复尝试和多次重新审查文档,我解决了此问题。我猜我有一个很糟糕的假设,即当提供商依赖于更改时提供商会更新。
我发现,一旦StreamProvider返回(或让步),直到处置掉它,它总是将返回与原始值相同的值,而不管依赖关系更改或来自Stream的事件如何。在这里,“计算”很有用,但是当您希望从提供程序返回AsyncValue时(StreamProvider的行为),它实际上并不能很好地工作。
此外,由于Flutter Inspector无法正确更新ProviderScope小部件而引起了其他混乱。我必须单击并刷新几次才能查看对提供程序或其状态的更新。反正...
class AuthService {
...
static final provider = StreamProvider.autoDispose((ref) {
final sub = FirebaseAuth.instance.onAuthStateChanged.listen((auth) => ref.read(uidProvider).state = auth?.uid);
ref.onDispose(() => sub.cancel());
return FirebaseAuth.instance.onAuthStateChanged;
});
static final uidProvider = StateProvider<String>((_) => null);
...
}
class User {
...
static final provider = StreamProvider.autoDispose((ref) {
final uid = ref.read(AuthService.uidProvider)?.state;
return Service.user.stream(uid);
});
...
鉴于用户退出应用程序后您的UI不再依赖提供程序(允许它们正确处置),此解决方案有效。