[英]Turning two streams into a single stream to pipe with read and write streams
[英]Flutter : stream two Streams into a single screen?
我有兩個流從兩個不同的 api 中獲取。
Stream<Month> get monthOutStream => monthOutController.stream;
Stream<MySchedule> get resultOutStream => resultController.stream;
我在應用程序的兩種不同狀態下獲取這些數據,即開始時的結果和來自用戶的某些事件后的幾個月。
MyScheduleBloc(){
initialData();
}
Future initialData() async {
MySchedule mySchedule = await myScheduleViewModel.importMySchedule(now.id);
resultController.add(mySchedule);
}
我的屏幕有一個流構建器
Widget build(BuildContext context) {
final webCalenderBloc = WebCalenderBloc();
return StreamBuilder(
stream: webCalenderBloc.resultOutStream,
builder: (BuildContext context , snapdata){
if(!snapdata.hasData){
return Center(
child: CircularProgressIndicator(),
);
}
return body(snapdata.data);
},
);
}
由於主要的小部件構建方法將帶有 resultoutstream 的 StreamBuilder 小部件作為流。我在哪里獲取另一個流月outStream。 我可以在流中獲取流嗎? 在處理兩個流時我是否遺漏了任何東西。我不想從monthoutstream 構建任何小部件,但想檢查其中的數據。
如果需要,您可以嵌套StreamBuilder
。 沒有什么可以阻止您執行以下操作:
StreamBuilder(
stream: stream1,
builder: (context, snapshot1) {
return StreamBuilder(
stream: stream2,
builder: (context, snapshot2) {
// do some stuff with both streams here
},
);
},
)
如果這對您有意義,另一種解決方案是:流被設計為可合並/轉換。 您可以制作第三個流,它是后面兩個流的合並。
理想情況下,對於復雜的流操作,您需要使用rxdart ,因為它提供了一些有用的轉換器。
使用 rxdart,兩個Observable
(它們是Stream
的子類)的融合如下:
Observable<bool> stream1;
Observable<String> stream2;
final fusion = stream1.withLatestFrom(stream2, (foo, bar) {
return MyClass(foo: foo, bar: bar);
});
Observable.combineLatest2(
aStream,
bStream,
(a, b, c) =>
a != '' && b != '');
combineLatestN 返回一個組合流
我正在使用一種 BLoC,我在其中廣播了Stream<Null>
,當某些事情發生變化時,它只會通知聽眾。 有點像 Qt 的信號和插槽。 無論如何,對於我想聽不止一個流的情況,我做了這門課。 它基本上StreamBuilder
但你可以收聽多個流,它會丟棄流中的任何數據。
import 'dart:async';
import 'package:flutter/widgets.dart';
typedef MultiStreamWidgetBuilder<T> = Widget Function(BuildContext context);
// A widget that basically re-calls its builder whenever any of the streams
// has an event.
class MultiStreamBuilder extends StatefulWidget {
const MultiStreamBuilder({
required this.streams,
required this.builder,
Key? key,
}) : super(key: key);
final List<Stream<dynamic>> streams;
final MultiStreamWidgetBuilder builder;
Widget build(BuildContext context) => builder(context);
@override
State<MultiStreamBuilder> createState() => _MultiStreamBuilderState();
}
class _MultiStreamBuilderState extends State<MultiStreamBuilder> {
final List<StreamSubscription<dynamic>> _subscriptions = [];
@override
void initState() {
super.initState();
_subscribe();
}
@override
void didUpdateWidget(MultiStreamBuilder oldWidget) {
super.didUpdateWidget(oldWidget);
if (oldWidget.streams != widget.streams) {
// Unsubscribe from all the removed streams and subscribe to all the added ones.
// Just unsubscribe all and then resubscribe. In theory we could only
// unsubscribe from the removed streams and subscribe from the added streams
// but then we'd have to keep the set of streams we're subscribed to too.
// This should happen infrequently enough that I don't think it matters.
_unsubscribe();
_subscribe();
}
}
@override
Widget build(BuildContext context) => widget.build(context);
@override
void dispose() {
_unsubscribe();
super.dispose();
}
void _subscribe() {
for (final s in widget.streams) {
final subscription = s.listen(
(dynamic data) {
setState(() {});
},
onError: (Object error, StackTrace stackTrace) {
setState(() {});
},
onDone: () {
setState(() {});
},
);
_subscriptions.add(subscription);
}
}
void _unsubscribe() {
for (final s in _subscriptions) {
s.cancel();
}
_subscriptions.clear();
}
}
示例使用:
class AppWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MultiStreamBuilder(
streams: [appState.repoListChanged, appState.selectedRepoChanged],
builder: _buildMain,
);
}
Widget _buildMain(BuildContext context) {
return Scaffold(
body: Row(
...
我只是寫了它,所以我沒有測試它。 我認為理論上你可以制作一個給你狀態的東西,雖然我不確定 Dart 的類型系統是否足夠先進,可以讓你在不依賴dynamic
的情況下做到這一點。
好吧,就我而言,如果它們屬於同一類型,我更喜歡將多個流合並為一個。 所以你可以使用:
import 'package:async/async.dart' show StreamGroup;
...
StreamGroup.merge([stream1,stream2]);
讓我們試試Rx.merge([stream1, stream2, ....])
Widget build(BuildContext context) {
return StreamBuilder3<int, int, int>(
streams: Tuple3(stream1, stream2, stream3),
initialData: Tuple3(0, 0, 0),
builder: (context, snapshots) {
return Text(
'stream1: ${snapshots.item1.data} - stream2: ${snapshots.item2.data} - stream3: ${snapshots.item3.data}',
);
},
);
}
Widget build(BuildContext context) {
return MultiStreamBuilder(
streams: [stream1, stream2],
builder: (context, dataList) {
final stream1Value = dataList[0];
final stream2Value = dataList[1];
return Text('$stream1Value, $stream2Value');
},
);
}
錯誤:顯示用於空值的空檢查運算符。 然后我把它放在 try{}catch(e){} 塊下 & 兩個流都工作正常.. 檢查圖片在此處輸入圖像描述
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.