Блок шаблонов для скрытия и отображения виджетов

Я пытаюсь получить некоторые данные из Интернета и показать их в списке.

Следующее мое bloc код

class StudentsBloc {
  final _repository = Repository();
  final _students = BehaviorSubject<StudentModel>();

  final BehaviorSubject<bool> _showProgress = BehaviorSubject<bool>();
  final BehaviorSubject<bool> _showNoInternetViews = BehaviorSubject<bool>();

  Observable<StudentModel> get students => _students.stream;
  Observable<bool> get showProgress => _showProgress.stream;
  Observable<bool> get showNoInternetViews => _showNoInternetViews.stream;

  //FetchStudent from my Api
  fetchStudents(String disciplineId, String schoolId, String year_id,
      String lastIndex) async {
    final student = await _repository.fetchStudents(
        disciplineId, schoolId, year_id, lastIndex);
    _students.sink.add(student);
  }

  //Check to see if user has internet or not
  isNetworkAvailable(String disciplineId, String schoolId, String year_id,
      String lastIndex) async {
    checkInternetConnection().then((isAvailable) {
      if (isAvailable) {
        fetchStudents(disciplineId, schoolId, year_id, lastIndex);
      } else {
        _students.sink.addError(NO_NETWORK_AVAILABLE);
      }
    });
  }

  Function(bool) get changeVisibilityOfProgress => _showProgress.sink.add;
  Function(bool) get changeVisibilityOfNoInternetViews =>
      _showNoInternetViews.sink.add;

  dispose() {
    _students.close();
    _showProgress.close();
    _showNoInternetViews.close();
  }
}

Ниже мой основной код, чтобы скрыть виджеты

Widget buildList(StudentsBloc bloc) {
    return StreamBuilder(
      stream: bloc.students,
      builder: (context, AsyncSnapshot<StudentModel> snapshot) {
        if (snapshot.hasError) {
          bloc.changeVisibilityOfProgress(false);
          bloc.changeVisibilityOfNoInternetViews(true);

          return StreamBuilder(
            stream: bloc.showNoInternetViews,
            builder: (context, snapshot) {
              bool showNoInternetView = snapshot.hasData ?? false;

              return Visibility(
                child: Center(
                  child: Column(
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: <Widget>[
                      Text("No Network Available"),
                      RaisedButton(
                        onPressed: () {
                          fetchStudents();
                        },
                        child: Text("Retry"),
                      )
                    ],
                  ),
                ),
                visible: showNoInternetView ? true : false,
              );
            },
          );
        }

        if (snapshot.hasData) {
          bloc.changeVisibilityOfProgress(false);
          bloc.changeVisibilityOfNoInternetViews(false);

          return Refresh(
            year_id: "2",
            schoolId: "1",
            lastIndex: "0",
            disciplineId: "1",
            child: ListView.builder(
              itemBuilder: (context, int index) {
                return buildTile(
                    snapshot.data.toBuilder().data.studentData[index]);
              },
              itemCount: snapshot.data.toBuilder().data.studentData.length,
            ),
          );
        }

        if (!snapshot.hasData) {
          return StreamBuilder(
            builder: (context, snapshot) {
              bool showProgressIndicator = snapshot.data ?? false;

              return Visibility(
                child: Center(
                  child: CircularProgressIndicator(),
                ),
                visible: showProgressIndicator ? true : false,
              );
            },
            stream: bloc.showProgress,
          );
        }
      },
    );
  }

buildList метод вызывается в body из Scaffold

void fetchStudents() {
    bloc?.changeVisibilityOfNoInternetViews(false);
    bloc?.changeVisibilityOfProgress(true);
    bloc?.isNetworkAvailable("1", "1", "2", "0");
  }

Предположим, у пользователя есть Интернет, когда приложение открыто, и я могу видеть circularprogressindicator и затем список данных виден, но предположим, что в начале, когда приложение открыто, и у пользователя нет Интернета, тогда я показываю текст "Нет сети доступен" и кнопку, чтобы повторить попытку, теперь, если пользователь подключился к Интернету, а затем нажмите кнопку, чтобы повторить попытку. Я сразу вижу список данных через несколько секунд вместо circularprogressindicatorЯ не могу понять, почему NoInternetviews не прячутся и progressindicator отображается при нажатии кнопки повтора перед отображением списка данных.

Мой поток не обновляется после вызова кнопки повтора. Есть ли какие-то предостережения для StreamBuilder в StreamBuilder?

Я пытался изменить StreamBuilder порядок, упомянутый @ivenxu в ответе, но он все равно не работает. Ниже приведены ссылки на прилагаемый код https://drive.google.com/file/d/15Z8jXw1OpwTB1CxDS8sHz8jKyHhLwJp7/view?usp=sharing https://drive.google.com/open?id=1gIXV20S1o5jYRnno_NADabuIj4w163fF

1 ответ

В слое вида вы можете использовать виджет Visibility() и передавать видимый параметр true или false при загрузке данных из Интернета. давайте подумаем, как изменить видимую переменную из блока. Родитель виджета Visibility() StreamBuilder() для потоковой передачи данных об изменениях. для вашего случая вам нужен PublishSubject внутри вашего блока для потоковой передачи и добавления новых данных, и Observable для потоковой передачи этих данных в вашем виджете.

давайте покажем фрагмент кода, чтобы помочь вам, как вы можете его реализовать

Блок содержит PublishSubject и Observable для потоковой передачи и добавления данных.

  //this Subject allows sending data, error and done events to the listener
  final PublishSubject<bool> _progressStateSubject = new PublishSubject();

  //the listener are streaming on changes
  Observable<bool> get progressStateStream => _progressStateSubject.stream;

  //to change your progress state
  void changeProgressState({bool state}) => _progressStateSubject.sink.add(state);

Здесь вы можете изменить состояние вашего прогресса

void callWebService() async {
    //when you call your func to fetch your data change your state to true
    changeProgressState(state: true);
    .
    .
    .
    if(response != null){
      //when your call is done change the state to false
      changeProgressState(state: false);
    }
  }

Ваш виджет прогресса

// Loading Widget
  Widget _buildLoadingWidget(Bloc bloc) {
    return StreamBuilder<bool>(
        stream: bloc.progressStateStream,//streaming on changes
        builder: (context, snapshot) {
          return Visibility(
            visible: snapshot.data ?? false,//calling when data changes
            child: Center(
              child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: <Widget>[
                  Text("Loading data from API...",
                      textDirection: TextDirection.ltr),
                  CircularProgressIndicator()
                ],
              ),
            ),
          );
        });
  }

Кажется, причина в том, что CircularProgressIndicator находится в цикле обновления потока студентов. И ученик получает только следующий снимок, когда данные возвращаются из интернет-звонка в случае повторной попытки.

Попробуйте изменить порядок потоковых компоновщиков, попробуйте поместить студенческий потоковый компоновщик в компоновщик прогрессивных потоков.

Widget buildList(StudentsBloc bloc) {
    return StreamBuilder(
      stream: bloc.showProgress,
      builder: (context, snapshot) {
        bool showProgressIndicator = snapshot.data ?? false;
        if (!showProgressIndicator) {
             StreamBuilder(
            stream: bloc.students,
            builder: (context, AsyncSnapshot<StudentModel> snapshot) {
               ....
               //your original code without progress StreamBuilder
            }
        }
        return Visibility(
        child: Center(
            child: CircularProgressIndicator(),
        ),
        visible: showProgressIndicator ? true : false,
        );
    },

    );
  }
Другие вопросы по тегам