#dart #flutter
#dart #флаттер
Вопрос:
Считайте, что у меня есть это
StreamBuilder(
stream: myBloc.productList,
builder: (context, AsyncSnapshot<List<Product>> snapshot) {
if (snapshot.hasData amp;amp; snapshot != null) {
if (snapshot.data.length > 0) {
return buildProductList(snapshot);
}
else if (snapshot.data.length==0){
return Center(child: Text('No Data'));
}
} else if (snapshot.hasError) {
return ErrorScreen(errMessage: snapshot.error.toString());
}
return CircularProgressIndicator();
},
),
Сначала индикатор выполнения будет работать нормально, но когда данные не найдены и как только отображается «Нет данных», индикатор выполнения больше никогда не появляется.
Как отображать индикатор выполнения только при загрузке данных. И не показывать данные, когда нет данных, и показывать данные, когда есть данные?
Вот как часть блока
final _fetcher = BehaviorSubject<List<Product>>();
Observable<List<Product>> get productList => _fetcher.stream;
Просто извлеките данные из RESTAPI, а затем поместите их в список
List<Product> product = await _repository.fetchProduct().catchError((err) => _fetcher.addError(err));
_fetcher.sink.add(product);
Комментарии:
1. Как вы реализовали поток списка продуктов в блоке?
2. Использование stream и sink. Позвольте мне обновить вопрос.
Ответ №1:
Прежде всего, snapshot.hasData
и snapshot.data != null
буквально одинаковы ( hasData
вызовы data != null
внутри). Я на самом деле неправильно прочитал ваш код там, но snapshot
никогда не будет null
. Таким образом, вы можете удалить его в любом случае.
Проблема здесь в том, что вы неправильно понимаете, как Stream
это работает. Поток не отправит обновление, если вы в данный момент добавляете product
. Как бы он узнал, когда это делать в любом случае? Он будет обновляться, только если вы вызовете add
его, и в этом случае data
не будет null
. Следовательно, индикатор выполнения отсутствует.
Вы можете легко исправить это, добавив null
при загрузке:
_fetcher.sink.add(null); // to show progress indicator
List<Product> product = await _repository.fetchProduct().catchError((err) => _fetcher.addError(err));
_fetcher.sink.add(product); // to show data
Комментарии:
1. Большое вам спасибо. Я попытался добавить _fecther.sink.add(null) Я думаю, это было неправильно
2. Извините, _fetcher.sink.add (null) также работает, возможно, проблема с горячей загрузкой, когда я впервые попробовал это
Ответ №2:
snapshot.connectionState
может определить, загружаются ли ваши данные…
if (snapshot.connectionState == ConnectionState.waiting) {
return CircularProgressIndicator();
}
Ответ №3:
Принятый ответ был вполне осуществим до того, как Dart перешел к нулевой безопасности, но теперь может быть немного неудобно, если вам придется изменить тип потока на T?
, чтобы иметь возможность передавать null в этих случаях. Итак, я предпочитаю другой подход сейчас. Я просто создаю специальную «ошибку»:
class StreamBuilderProgress extends Error {}
и передайте это в список, когда придет время:
list.addError(StreamBuilderProgress());
и убедитесь, что я возвращаю индикатор выполнения всякий раз, когда snapshot.hasError amp;amp; snapshot.error is StreamBuilderProgress
.
Ответ №4:
StreamBuilder<List<Room>>(
stream: roomsSource.stream,
builder: (context, snapshot) {
if(snapshot.connectionState == ConnectionState.waiting){
print("loading data");
}else if(!snapshot.hasData || snapshot.data!.isEmpty){
print("no data");
}else if(snapshot.hasData amp;amp; snapshot.data!.isNotEmpty){
print("has data");
}else {
print("error");
}
}
)