如何组合 2 个 Riverpod StreamProvider,其中 1 个流依赖于另一个流的数据?
How do you combine 2 Riverpod StreamProviders where 1 stream depends on the data from another stream?
有时我认为我正在理解提供者的逻辑,然后我在尝试做下面这样的事情时被难住了几个小时。
我需要从 firestore collectionsstream 获取连接 ID 列表。简单。
但是,我需要将这个连接 ID 的流列表提供给另一个 firestore collectionstream。在下面,您可以看到我即将到来的 EventsStreamProvider 是 ref.watch 数据库和连接流。 riverpod 或 firestore 不会抛出任何错误。但是,在日志中,我按以下顺序看到我的打印语句:
returned data
returned null stream value
我如何滥用 Riverpod 提供商的权力?哈哈
final connectionsStreamProvider = StreamProvider<List<UidConnections>>((ref) {
final database = ref.watch(databaseProvider);
return database != null ? database.connectionsStream() : Stream.value(null);
});
final connectionsListStateProvider = StateProvider<List>((ref) => []);
final upcomingEventsStreamProvider = StreamProvider<List<SpecialEvents>>((ref) {
final database = ref.watch(databaseProvider);
final connectionsStream = ref.watch(connectionsStreamProvider);
if (database != null && connectionsStream != null) {
connectionsStream.whenData((data) {
if (data != null) {
data.forEach((event) {
if (event?.active == true && event?.connectedUid != null) {
ref
.read(connectionsListStateProvider)
.state
.add(event.connectedUid);
}
});
print('returned data');
return database.upcomingSpecialEventsStream(
ref.read(connectionsListStateProvider).state);
}
});
}
print('returned null stream value');
return Stream.value(null);
});
或者,我是否只需要重构我的 Firebase Cloud Firestore 查询以首先获取连接 ID 流?我宁愿使用 Riverpod,因为我仍然需要单独的连接 ID 流。
仍然对如何单独使用 Riverpod 完成 2 个流的组合感到困惑。但是,我确实设法解决了我的问题,下面是遇到此用例的任何其他人的信息,其中一个流依赖于另一个流的数据。
有效的解决方案是使用 rxdart Rx.combineLatest2
,我可能会补充说非常好。见下文。现在 Riverpod 很高兴,并为我的组合流提供状态。感谢 rxdart,我需要的连接 ID 现在是我的帐户模型的一部分。希望这对外面的人有帮助。
final accountInfoStreamProvider = StreamProvider<Account>((ref) {
final database = ref.watch(databaseProvider);
return database != null
? AccountInfoModel(database: database).accountInfoStream()
: Stream.value(null);
});
class AccountInfoModel {
AccountInfoModel({@required this.database});
final FirestoreDatabase database;
Stream<Account> accountInfoStream() {
return Rx.combineLatest2(
database.accountStream(),
database.connectionsStream(),
(Account account, List<Connections> connections) {
connections.forEach((connection) {
account.connections.add(connection.documentId);
});
return account;
},
);
}
}
有时我认为我正在理解提供者的逻辑,然后我在尝试做下面这样的事情时被难住了几个小时。
我需要从 firestore collectionsstream 获取连接 ID 列表。简单。
但是,我需要将这个连接 ID 的流列表提供给另一个 firestore collectionstream。在下面,您可以看到我即将到来的 EventsStreamProvider 是 ref.watch 数据库和连接流。 riverpod 或 firestore 不会抛出任何错误。但是,在日志中,我按以下顺序看到我的打印语句:
returned data
returned null stream value
我如何滥用 Riverpod 提供商的权力?哈哈
final connectionsStreamProvider = StreamProvider<List<UidConnections>>((ref) {
final database = ref.watch(databaseProvider);
return database != null ? database.connectionsStream() : Stream.value(null);
});
final connectionsListStateProvider = StateProvider<List>((ref) => []);
final upcomingEventsStreamProvider = StreamProvider<List<SpecialEvents>>((ref) {
final database = ref.watch(databaseProvider);
final connectionsStream = ref.watch(connectionsStreamProvider);
if (database != null && connectionsStream != null) {
connectionsStream.whenData((data) {
if (data != null) {
data.forEach((event) {
if (event?.active == true && event?.connectedUid != null) {
ref
.read(connectionsListStateProvider)
.state
.add(event.connectedUid);
}
});
print('returned data');
return database.upcomingSpecialEventsStream(
ref.read(connectionsListStateProvider).state);
}
});
}
print('returned null stream value');
return Stream.value(null);
});
或者,我是否只需要重构我的 Firebase Cloud Firestore 查询以首先获取连接 ID 流?我宁愿使用 Riverpod,因为我仍然需要单独的连接 ID 流。
仍然对如何单独使用 Riverpod 完成 2 个流的组合感到困惑。但是,我确实设法解决了我的问题,下面是遇到此用例的任何其他人的信息,其中一个流依赖于另一个流的数据。
有效的解决方案是使用 rxdart Rx.combineLatest2
,我可能会补充说非常好。见下文。现在 Riverpod 很高兴,并为我的组合流提供状态。感谢 rxdart,我需要的连接 ID 现在是我的帐户模型的一部分。希望这对外面的人有帮助。
final accountInfoStreamProvider = StreamProvider<Account>((ref) {
final database = ref.watch(databaseProvider);
return database != null
? AccountInfoModel(database: database).accountInfoStream()
: Stream.value(null);
});
class AccountInfoModel {
AccountInfoModel({@required this.database});
final FirestoreDatabase database;
Stream<Account> accountInfoStream() {
return Rx.combineLatest2(
database.accountStream(),
database.connectionsStream(),
(Account account, List<Connections> connections) {
connections.forEach((connection) {
account.connections.add(connection.documentId);
});
return account;
},
);
}
}