Мне нужно реализовать поиск и отобразить результаты.Я использую Observables из RxDart.
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
, потому что моя наблюдаемая выдает SearchEmpty, но я получаю false .Что я сделал не так?Все, что мне нужно, это просто отображать какое-то сообщение, если результат поиска пуст.
UPD: После дополнительного изучения StreamBuilder, чтения документов RxDart и систематизации информации из pskink я пришел к выводу, что яошибся switchIfEmpty () означает, что поток переключается на резервный, только если исходный поток ничего не возвращает (после помещения значения в sink ).Мне нужно использовать startWith () , который заставляет наблюдаемое излучать требуемое start значение.Таким образом, правильный код
Observable<SearchState> get result {
return _searchSubject.switchMap((term) {
return _search(term); // returns Observable<SearchCompleted>
}).startWith(SearchEmpty());
}
UPD2: при первой сборке виджета StreamBuilder snapshop.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(...);}
}
}
),