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

#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");
            }
        }
)