我正试图将来自两个不同集合的两个流(第一个是"avvenmenti",第二个是"prospective"(组合成一个返回一个ListView的StreamBuilder。
我尝试了很多选项(使用Rx、返回StremBuilder并返回ListView的StreamBuilder等(,但未能将它们适应我的项目。
在ListView的children属性上,我只能添加一个List:
return StreamBuilder(
stream: Global.avvenimentiRef.streamData(),
builder: (context, snap1) {
if (snap1.hasData) {
List<Avvenimento> avvenimenti = snap1.data;
return StreamBuilder(
stream: Global.prospettiveRef.streamData(),
builder: (context, snap2) {
if (snap2.hasData) {
List<Prospettive> prospettive = snap2.data;
return Scaffold(
//this is the single ListView i want to use
body: ListView(
primary: false,
padding: const EdgeInsets.only(top: 20, bottom: 20),
children:
prospettive.map((prospettiveId) => ProspettiveItem(prospettiveId: prospettiveId)).toList(),
avvenimenti
.map((avvenimentoId) =>
AvvenimentoItem(avvenimentoId: avvenimentoId))
.toList(),
),
);
} else {
return LoadingScreen();
}
},
);
} else {
return LoadingScreen();
}
},
);
}
我的数据库:
lass Document<T> {
final FirebaseFirestore _db = FirebaseFirestore.instance;
final String path;
DocumentReference ref;
Document({this.path}) {
ref = _db.doc(path);
}
Future<T> getData() {
return ref.get().then((v) => Global.models[T](v.data()) as T);
}
Stream<T> streamData() {
return ref.snapshots().map((v) => Global.models[T](v.data()) as T);
}
Future<void> upsert(Map data) {
return ref.set(Map<String, dynamic>.from(data));
}
}
class Collection<T> {
final FirebaseFirestore _db = FirebaseFirestore.instance;
final String path;
CollectionReference ref;
Collection({this.path}) {
ref = _db.collection(path);
}
Future<List<T>> getData() async {
var snapshot = await ref.get();
return snapshot.docs
.map((doc) => Global.models[T](doc.data()) as T)
.toList();
}
Stream<List<T>> streamData() {
return ref.snapshots().map((list) =>
list.docs.map((doc) => Global.models[T](doc.data()) as T).toList());
}
}
型号:
class ElencoProspettive {
String fonte;
String title;
ElencoProspettive({this.fonte, this.title});
ElencoProspettive.fromMap(Map data) {
fonte = data['data'] ?? '';
title = data['title'] ?? '';
}
}
class Prospettive {
String id;
String titlePro;
List<ElencoProspettive> elenco;
Prospettive({this.id, this.titlePro, this.elenco});
factory Prospettive.fromMap(Map data) {
return Prospettive(
id: data['data'] ?? '',
titlePro: data['title'] ?? '',
elenco: (data['elenco'] as List ?? [])
.map((v) => ElencoProspettive.fromMap(v))
.toList());
}
}
型号:
class Global {
//
// App Data
//
static final String title = 'Annales';
static final FirebaseAnalytics analytics = FirebaseAnalytics();
static final Map models = {
Avvenimento: (data) => Avvenimento.fromMap(data),
Prospettive: (data) => Prospettive.fromMap(data),
};
static final Collection<Avvenimento> avvenimentiRef =
Collection<Avvenimento>(path: 'avvenimenti');
static final Collection<Prospettive> prospettiveRef =
Collection<Prospettive>(path: 'propsettive');
}
使用Rx
中的CombineLatestStream,因为您已经尝试过了。
StreamBuilder(
stream: CombineLatestStream.list([
Global.avvenimentiRef.streamData(),
Global.prospettiveRef.streamData(),
]),
builder: (context, snap1)
- 请注意,如果其中一个流发生更改,则将重新加载您的
StreamBuilder
- 您可以使用
snap1.data[0]
或snap1.data[1]
访问流返回的数据。。ect
对于列表,您可以尝试
ListView(
primary: false,
padding: const EdgeInsets.only(top: 20, bottom: 20),
children:
[...(prospettive.map((prospettiveId) => ProspettiveItem(prospettiveId: prospettiveId)).toList()),
...(avvenimenti
.map((avvenimentoId) =>
AvvenimentoItem(avvenimentoId: avvenimentoId))
.toList())],
),
如果你不想安装软件包,也不想嵌套你的StreamBuilder
,你可以尝试这个Dart香草解决方案:当提供的任何流勾选某个内容时,我勾选了一个流控制器:
/// Merge all [streams] events into a single [Stream] that emits void
/// when any of the [streams] emits an event.
Stream<void> combineStreams(List<Stream<dynamic>> streams) {
late final StreamController<void> controller;
final subscriptions = <StreamSubscription<dynamic>>[];
Future<void> onCancel() async {
for (final subscription in subscriptions) {
await subscription.cancel();
}
}
void onListen() {
for (final stream in streams) {
subscriptions.add(
stream.listen(
(event) {
controller.add(null);
},
),
);
}
}
void onPause() {
for (final subscription in subscriptions) {
subscription.pause();
}
}
void onResume() {
for (final subscription in subscriptions) {
subscription.resume();
}
}
controller = StreamController<void>(
onCancel: onCancel,
onListen: onListen,
onPause: onPause,
onResume: onResume,
);
return controller.stream;
}
返回的流的类型为Stream<void>
,因此您无法从中访问事件值,您需要引用原始流引用来获得其当前值。
Flutter中将两个立方体流合并为单个StreamBuilder
:的示例用法
StreamBuilder<void>(
stream: combineStreams([
isLoadingCubit.stream,
isVisibleCubit.stream,
]),
builder: (context, snapshot) {
if (!isVisibleCubit.state) {
return Container();
}
if (isLoadingCubit.state) {
return MyLoadingSpinner();
}
return MyDataWidget();
},
)