Мне нужно реализовать поиск и отображение результатов. Я использую 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 используется этот результат как источник для потока. И при открытии экрана (без поиска) я ожидаю, что
snapshot.hasData = true
потому что мой наблюдаемый выводит SearchEmpty, но я получаю false. Что я сделал не так? Все, что мне нужно, это просто отобразить какое-нибудь сообщение, если результат поиска пуст.
UPD: После дополнительного исследования StreamBuilder, чтения документации RxDart и систематизации информации из pskink я пришел к выводу, что ошибался. switchIfEmpty () означает, что поток переключается на резервный, только если исходный поток ничего не возвращает (после помещения значения в приемник). Мне нужно использовать startWith (), который заставляет наблюдаемое излучать обязательное начальное значение. Итак, правильный код
Observable<SearchState> get result {
return _searchSubject.switchMap((term) {
return _search(term); // returns Observable<SearchCompleted>
}).startWith(SearchEmpty());
}
UPD2: при первой сборке snapshop.hasData = false
виджета StreamBuilder, даже с использованием 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(...);}
}
}
),
search(term)
, если ничего не найдено?Observable.empty()
? - person pskink   schedule 21.05.2019PublishSubject<String> subject = PublishSubject(); subject .switchMap((s) => _search(s).switchIfEmpty(Observable.just('*** NOT FOUND ***'))) .listen(print);
- проверьте это гипотетическим_search()
методом:Observable<String> _search(String term) { return term.length < 8 ? Observable.just('[$term]') : Observable.empty(); }
- person pskink   schedule 21.05.2019_searchSubject.add('test')
, я увидел test Эта модификацияsubject.switchMap((s) => _search(s)).switchIfEmpty(Observable.just('*** NOT FOUND ***')).listen(print);
также не дает ответа. - person BambinoUA   schedule 21.05.2019Observable#startWith
может быть? - person pskink   schedule 21.05.2019