将多个 BehaviorSubject 流合并为一个?
Combine multiple BehaviorSubject streams into one?
我的目标是使用多个流而不必嵌套 3 个以上的 StreamBuilder。
我已经在使用 rxdart 并且研究了 mergewith 但我真的不明白使用它的正确语法?
我目前有一个名为 InfoBloc
的 Bloc 文件。这是InfoBloc
里面的代码
final _name = BehaviorSubject<String>();
final _description = BehaviorSubject<String>();
final _picture = BehaviorSubject<File>();
Observable<String> get name => _name.stream.transform(_validateName);
Observable<File> get picture => _picture.stream;
Observable<String> get eventDescription =>
_description.stream.transform(_validateMessage);
final _validateMessage = StreamTransformer<String, String>.fromHandlers(
handleData: (eventMessage, sink) {
if (eventMessage.length > 0) {
sink.add(eventMessage);
} else {
sink.addError(StringConstant.eventValidateMessage);
}
});
var obs = Observable.merge([])
final _validateName = StreamTransformer<String, String>.fromHandlers(
handleData: (String name, sink) {
if (RegExp(r'[!@#<>?":_`~;[\]\|=+)(*&^%0-9-]').hasMatch(name)) {
sink.addError(StringConstant.nameValidateMessage);
} else {
sink.add(name);
}
});
void dispose() async {
await _description.drain();
_description.close();
await _name.drain();
_name.close();
await _picture.drain();
_picture.close();
}
现在在小部件内部,我需要名称、图片和描述快照。所以我通常会做
StreamBuilder(
stream: _bloc.name,
builder: (BuildContext context, AsyncSnapshot<String> snapshotName) {
return StreamBuilder(
stream: _bloc.eventDescription,
builder: (BuildContext context, AsyncSnapshot<String> snapshotDescription) {
return StreamBuilder(
stream: _bloc.picture,
builder: (BuildContext context, AsyncSnapshot<File> snapshotName) {
但是必须有更好的方法来做到这一点。
我的梦想是我可以在 InfoBloc
文件中制作一些东西,可以组合所有这些流,我只需要使用一次 StreamBuilder 来流式传输组合的流。
您可以检查 Observable
class 的 combineLatest()
方法。它通过使用组合器函数将给定的流合并到一个 Observable 序列中,这样生成的 Observable 将不会发射,除非所有流都发射了至少一项。
有一堆combineLatest()
方法。但是因为你有 3 个流,你可以使用 combineLatest3()
.
例子-
Observable.combineLatest3(
new Observable.just("a"),
new Observable.just("b"),
new Observable.fromIterable(["c", "c"]),
(a, b, c) => a + b + c)
.listen(print); //prints "abc", "abc"
您可以查看 this link 了解更多信息。
更新 -
您可以参考下面的例子在您的代码中使用该函数。
Observable<String> get name => _name.stream.transform(_validateName);
Observable<File> get picture => _picture.stream;
Observable<String> get eventDescription => _description.stream.transform(_validateMessage);
//Add this line to combine your Streams
Observable<bool> readyToSubmit => Observable.combineLatest3(name, picture, eventdescription, (value1, value2, value3) => true);
//We simply return true from the combiner function since we don't want to perform any operation on the Streams when combining.
例如,我使用了 bool
类型 Observable
。您可以将类型更改为可以使用的 Map<String, dynamic>' and add the Stream values into the
Mapif you want to access the data from all three streams. And in your
StreamBuilder` 小部件 -
StreamBuilder(
stream: _bloc.readyToSubmit,
builder: //Your builder function here
)
希望对您有所帮助!
我用这个 rxdart
:
Rx.combineLatest2(behaviorSubject1, behaviorSubject2, (String mail, String subject) {
return (mail.isNotEmpty && subject.isNotEmpty);
}).listen((event) {
event ? _enableButton.add(true) : _enableButton.add(false);
});
我的目标是使用多个流而不必嵌套 3 个以上的 StreamBuilder。
我已经在使用 rxdart 并且研究了 mergewith 但我真的不明白使用它的正确语法?
我目前有一个名为 InfoBloc
的 Bloc 文件。这是InfoBloc
final _name = BehaviorSubject<String>();
final _description = BehaviorSubject<String>();
final _picture = BehaviorSubject<File>();
Observable<String> get name => _name.stream.transform(_validateName);
Observable<File> get picture => _picture.stream;
Observable<String> get eventDescription =>
_description.stream.transform(_validateMessage);
final _validateMessage = StreamTransformer<String, String>.fromHandlers(
handleData: (eventMessage, sink) {
if (eventMessage.length > 0) {
sink.add(eventMessage);
} else {
sink.addError(StringConstant.eventValidateMessage);
}
});
var obs = Observable.merge([])
final _validateName = StreamTransformer<String, String>.fromHandlers(
handleData: (String name, sink) {
if (RegExp(r'[!@#<>?":_`~;[\]\|=+)(*&^%0-9-]').hasMatch(name)) {
sink.addError(StringConstant.nameValidateMessage);
} else {
sink.add(name);
}
});
void dispose() async {
await _description.drain();
_description.close();
await _name.drain();
_name.close();
await _picture.drain();
_picture.close();
}
现在在小部件内部,我需要名称、图片和描述快照。所以我通常会做
StreamBuilder(
stream: _bloc.name,
builder: (BuildContext context, AsyncSnapshot<String> snapshotName) {
return StreamBuilder(
stream: _bloc.eventDescription,
builder: (BuildContext context, AsyncSnapshot<String> snapshotDescription) {
return StreamBuilder(
stream: _bloc.picture,
builder: (BuildContext context, AsyncSnapshot<File> snapshotName) {
但是必须有更好的方法来做到这一点。
我的梦想是我可以在 InfoBloc
文件中制作一些东西,可以组合所有这些流,我只需要使用一次 StreamBuilder 来流式传输组合的流。
您可以检查 Observable
class 的 combineLatest()
方法。它通过使用组合器函数将给定的流合并到一个 Observable 序列中,这样生成的 Observable 将不会发射,除非所有流都发射了至少一项。
有一堆combineLatest()
方法。但是因为你有 3 个流,你可以使用 combineLatest3()
.
例子-
Observable.combineLatest3(
new Observable.just("a"),
new Observable.just("b"),
new Observable.fromIterable(["c", "c"]),
(a, b, c) => a + b + c)
.listen(print); //prints "abc", "abc"
您可以查看 this link 了解更多信息。
更新 -
您可以参考下面的例子在您的代码中使用该函数。
Observable<String> get name => _name.stream.transform(_validateName);
Observable<File> get picture => _picture.stream;
Observable<String> get eventDescription => _description.stream.transform(_validateMessage);
//Add this line to combine your Streams
Observable<bool> readyToSubmit => Observable.combineLatest3(name, picture, eventdescription, (value1, value2, value3) => true);
//We simply return true from the combiner function since we don't want to perform any operation on the Streams when combining.
例如,我使用了 bool
类型 Observable
。您可以将类型更改为可以使用的 Map<String, dynamic>' and add the Stream values into the
Mapif you want to access the data from all three streams. And in your
StreamBuilder` 小部件 -
StreamBuilder(
stream: _bloc.readyToSubmit,
builder: //Your builder function here
)
希望对您有所帮助!
我用这个 rxdart
:
Rx.combineLatest2(behaviorSubject1, behaviorSubject2, (String mail, String subject) {
return (mail.isNotEmpty && subject.isNotEmpty);
}).listen((event) {
event ? _enableButton.add(true) : _enableButton.add(false);
});