Могу ли я пропустить визуализацию BlocBuilder в некоторых случаях? - PullRequest
0 голосов
/ 24 мая 2019

Есть экран с блоком MyBloc myBloc

В методе построения экрана это выглядит так:

Widget build(BuildContext context) {
    return MyCustomLoadingStack( //My custom widget to have the main content below the loading widget
        _buildContent(context), //My main content
        _buildLoading(context)); //My loading on top
}

И мой метод 2:

Widget _buildContent(BuildContext context) {
 return Column(children: <Widget>[
      OtherWidgetOne(),
      OtherWidgetTwo(),
      BlocBuilder<MyEvent, MyState>(
          bloc: myBloc,
          builder: (BuildContext context, MyStatestate) {
            switch (state.type) {
              case MyStateList.doneWorking:
                return MyDataWidget(); // this content cares about displaying the data only
              default:
                return Container(); //otherwise display nothing
            }
          },
        )
]);

}

Widget _buildLoading(BuildContext context) {
 return BlocBuilder<MyEvent, MyState>(
          bloc: myBloc,
          builder: (BuildContext context, MyState state) {
            switch (state.type) {
              case MyStateList.loading:
                return LoadingView(); //This _buildLoading cares the loading only
              default:
                return Container(); //If it's not loading the show nothing for the loading layer
            }
          },
        )
}

Моя проблема в том, что в данный момент содержимое показывает данные.Когда я yield MyState(type: MyStateList.loading), чтобы показать загрузку, когда делать что-то еще (например, загрузить больше для данных, которые в данный момент отображаются).Вызываются оба BlocBuilder, а затем _buildContent(context) ничего не показывают, поскольку они не удовлетворяют условию MyStateList.doneWorking.И, конечно же, _buildLoading(context) показывает загрузку на пустом содержимом ниже.

Можно ли в любом случае пропустить BlocBuilder внутри _buildContent(context), чтобы продолжать показывать текущие данные и при этом сохранять загрузку сверху?

Хотя я хотел бы иметь виджет, содержащий данные или пустой Container() для использования в случае по умолчанию _buildContent(context), но это не имеет смысла для меня, потому что они могут повторно визуализировать один и тот же виджет.

Спасибо, что уделили время.

Ответы [ 2 ]

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

Для решения этой проблемы сейчас обсуждается запрос на получение ответа: https://github.com/felangel/bloc/issues/315?fbclid=IwAR2x_Q1x5MIUUPE7zFRpjNkhjx5CzR0qiRx-P3IKZR_VRGEp3eqQisTthDo

На данный момент вы можете использовать класс для более сложного состояния. Это может быть что-то вроде:

class MyState extends Equatable {
  final bool isLoading;
  final List<MyData> data;
  bool get hasData => data.isNotEmpty;

  MyState(this.isLoading,this.data) : super([isLoading,data]);
}

Я использую Equatable (https://pub.dev/packages/equatable) для более легкой реализации isEqual.

Widget _buildContent(BuildContext context) {
  return Column(children: <Widget>[
    OtherWidgetOne(),
    OtherWidgetTwo(),
    BlocBuilder<MyEvent, MyState>(
      bloc: myBloc,
      builder: (BuildContext context, MyStatestate) {
        if (state.hasData) {
          return MyDataWidget(); // this content cares about displaying the data only
        } else {
          return Container(); //otherwise display nothing
        }
      },
    )
  ]);
}

Widget _buildLoading(BuildContext context) {
  return BlocBuilder<MyEvent, MyState>(
    bloc: myBloc,
    builder: (BuildContext context, MyState state) {
      if (state.isLoading) {
          return LoadingView(); //This _buildLoading cares the loading only
      } else {
        return Container(); //If it's not loading the show nothing for the loading layer
      }
    },
  );
}

Недостатком этого метода является то, что виджет данных будет перерисовываться, даже если данные не изменяются. Это будет исправлено с помощью упомянутого pullrequest.

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

Отличный вопрос! Есть ли причина, по которой вы используете BlocBuilder вместо StreamBuilder?

Чтобы ничего не показывать во время загрузки данных и автоматического заполнения данных после их загрузки, я обычно делаю следующее:

   Widget _buildLoading(BuildContext context) {
     return StreamBuilder<Model>(
              stream: bloc.modelStream,
              builder: (context, snapshot) {

    if (snapshot.hasError) return _buildErrorWidget(snapshot.error, context);

    if (snapshot.hasData) {
              return DesiredWidget()
    } else {
    return LoadingView()
    }
}

Я не видел ваш файл BloC, но вам, возможно, придется добавить пару строк, например:

final _modelFetcher = BehaviorSubject<Model>();
Stream<Model> get modelStream => _modelFetcher.stream;

Function(Model) get changeModelFetcher => _modelFetcher.sink.add;


@override
  void dispose() async {
    await _modelFetcher.drain();
    _modelFetcher.close();
}

Дайте мне знать, если это поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...