在Streambuilder中组合两个流,并返回一个ListView(Flutter)



我正试图将来自两个不同集合的两个流(第一个是"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();
},
)

相关内容

  • 没有找到相关文章

最新更新