在RX中,有一个使用回调函数组合流结果的RX.combineLatest
方法。问题是,只有当每个流发出一个值时,它才会发出一个值。如果一个人没有,它就不会发出。
每当任何流序列发出项时,通过使用组合器函数将给定的流合并成单个流序列。在所有流至少发出一项之后,流才会发出。
Im试图将多个流合并到一个流中进行验证,当流没有发出或发出空值时,应该发出false或true。
class FormBloc {
final BehaviorSubject<bool> _result = BehaviorSubject();
final BehaviorSubject<String?> _usernameController = BehaviorSubject();
final BehaviorSubject<String?> _emailController = BehaviorSubject();
// Will only emit if each stream emitted a value
// If only username is emitted valid is not emitted
Stream<bool> get valid$ => Rx.combineLatest2(
_usernameController.stream,
_emailController.stream,
(username, email) => username != null || email != null
);
}
我如何加入这些流,以便如果valid$
的任何流的发生变化,它就会发出一个值?
发布于 2022-03-15 12:48:39
因为这里的所有解决方案都是解决方案,所以我实现了自己的流类。实现等于原始的CombineLatestStream实现,只是它不等待所有流发出后才发出:
import 'dart:async';
import 'package:rxdart/src/utils/collection_extensions.dart';
import 'package:rxdart/src/utils/subscription.dart';
class CombineAnyLatestStream<T, R> extends StreamView<R> {
CombineAnyLatestStream(List<Stream<T>> streams, R Function(List<T?>) combiner) : super(_buildController(streams, combiner).stream);
static StreamController<R> _buildController<T, R>(
Iterable<Stream<T>> streams,
R Function(List<T?> values) combiner,
) {
int completed = 0;
late List<StreamSubscription<T>> subscriptions;
List<T?>? values;
final _controller = StreamController<R>(sync: true);
_controller.onListen = () {
void onDone() {
if (++completed == streams.length) {
_controller.close();
}
}
subscriptions = streams.mapIndexed((index, stream) {
return stream.listen(
(T event) {
final R combined;
if (values == null) return;
values![index] = event;
try {
combined = combiner(List<T?>.unmodifiable(values!));
} catch (e, s) {
_controller.addError(e, s);
return;
}
_controller.add(combined);
},
onError: _controller.addError,
onDone: onDone
);
}).toList(growable: false);
if (subscriptions.isEmpty) {
_controller.close();
} else {
values = List<T?>.filled(subscriptions.length, null);
}
};
_controller.onPause = () => subscriptions.pauseAll();
_controller.onResume = () => subscriptions.resumeAll();
_controller.onCancel = () {
values = null;
return subscriptions.cancelAll();
};
return _controller;
}
}
发布于 2022-02-12 05:59:44
创建新的流,它释放当前的价值,并倾听该流是我的最佳实践。
class FormBloc {
final BehaviorSubject<bool> _result = BehaviorSubject();
final BehaviorSubject<String?> _usernameController = BehaviorSubject();
final BehaviorSubject<String?> _emailController = BehaviorSubject();
final _usernameStreamController = StreamController<String?>()
..add(_usernameController.value)
..addStream(_usernameController.stream);
final _emailStreamController = StreamController<String?>()
..add(_emailController.value)
..addStream(_emailController.stream);
Stream<bool> get valid$ => Rx.combineLatest2(
_usernameStreamController.stream, // use streamController instead
_emailStreamController.stream, // use streamController instead
(username, email) => username != null || email != null
);
}
发布于 2022-03-04 07:04:13
您可以使用一个BehaviorSubject<Map<String, String?>>
来发出用户名或电子邮件中的更改,而不是组合多个流。
add
要么更改\提交的用户名,要么向BehaviorSubject
发送电子邮件
_usernameEmailController.add({"uname": value},);
或
_usernameEmailController.add({"email": value},);
这样您就可以通过侦听来验证输入。我使用StreamBuilder
来显示发出的值,
StreamBuilder<Map<String, String?>>(
stream: _usernameEmailController.stream
.map((data) {
_r = {..._r, ...data};
return _r;
}),
builder: (context, snapshot) {
return Column(
children: [
Text(snapshot.data.toString()),
if (snapshot.hasData)
Text(
"Is valid?: "
"${(snapshot.data!["uname"] != null && snapshot.data!["uname"]!.isNotEmpty) || (snapshot.data!["email"] != null && snapshot.data!["email"]!.isNotEmpty)}"
),
],
);
},
),
在DartPad 这里上查看我的解决方案。
在DartPad中,我使用了StreamController
而不是BehaviorSubject
,因为DartPad不支持rxdart
包。但是您可以在DartPad中替换第40行
final StreamController<Map<String, String?>> _usernameEmailController =
StreamController();
使用
final BehaviorSubject<Map<String, String?>> _usernameEmailController =
BehaviorSubject();
如果您想使用BehaviorSubject
。
https://stackoverflow.com/questions/70361479
复制相似问题