我需要实现搜索和显示结果。我使用来自 RxDart 的 Observables。
abstract class SearchState {}
class SearchCompleted extends SearchState {}
class SearchEmpty extends SearchState {}
final _searchSubject = PublishSubject<String>();
Observable<SearchState> get result {
return _searchSubject.switchMap((term) {
return _search(term); // returns Observable<SearchCompleted>
}).switchIfEmpty(Observable.just(SearchEmpty()));
}
StreamBuilder 中的某个地方将此结果用作stream的源。在打开屏幕(没有搜索)我希望
snapshot.hasData = true
因为我的 observable 发出了 SearchEmpty 但我得到了 false。我做错了什么?如果搜索结果为空,我只需要显示一些消息。
UPD:在对 StreamBuilder 进行额外调查、阅读 RxDart 文档和 pskink 信息系统化之后,我得出的结论是我错了。switchIfEmpty()表示仅当原始流不返回任何内容(将值放置到sink之后)时才将流切换到回退。我需要使用startWith()来强制 observable 发出所需的起始值。所以正确的代码是
Observable<SearchState> get result {
return _searchSubject.switchMap((term) {
return _search(term); // returns Observable<SearchCompleted>
}).startWith(SearchEmpty());
}
UPD2:在第一次构建小部件 StreamBuildersnapshop.hasData = false
时,甚至使用 startWith() 因为connectionStatus = ConnectionStatus.waiting
(即当流准备接收数据时)。为避免这种情况,您必须为initialData属性设置值。例如:
StreamBuilder(
initialData: SearchEmpty(),
stream: result,
builder: ...
)
或者您可以在连接处于等待状态时返回一些小部件。例如:
StreamBuilder(
stream: result,
builder: (context, snapshot) {
// this allow to skip using `initialData`
if (snapshot.connectionStatus == ConnectionStatus.waiting) {
return Center(child: CircularProgressIndicator());
}
// Process data
if (snapshot.hasData) {
if (snapshot.data is SearchEmpty()) { return Text('no items');}
if (snapshot.data is SearchCompleted()) { return ListView(...);}
}
}
),