Почему свойство hasData StreamBuilder не имеет значения True, если Observable выдает событие? - PullRequest
0 голосов
/ 20 мая 2019

Мне нужно реализовать поиск и отобразить результаты.Я использую 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(...);}
    }
  }
),

1 Ответ

0 голосов
/ 21 мая 2019

У меня только что было что-то подобное в данный момент, я работал над этим, получая DataSnapshot, который возвращает null, если нет ключа / значения.

if (snapshot.hasData && snapshot.data.snapshot.value != null) {
  return //your code
}
else if(snapshot.hasData && snapshot.data.snapshot.value == null){
  return //no items found
}
else{
  return //your code
}

Таким образом, я мог бы управлять StreamBuilder, когда у него нет данных.

Это бы сработало:

if(snapshot.hasData){
  if(snapshot.data.snapshot.value == null){
    return //no data found
  }
  else{
    return //data
  }
}
...