Трепещущий блок заполняет начальное состояние данными

#flutter #dart #bloc #flutter-bloc

#трепетание #дротик #блок #трепещущий блок

Вопрос:

У меня есть вопрос о правильном размещении кода блока, так сказать. Так как bloc обозначает компонент бизнес-логики, я переместил бизнес-логику (например, методы обработки данных) внутрь класса. Итак, теперь есть 2 метода, один для получения, а второй для сохранения данных. Далее, у меня есть мой компонент, который внутри AddInitial должен показывать загрузку, затем запускает блок, говоря: «Эй, мне нужны данные здесь». Это правильно или это антипаттерн? Код выглядит следующим образом.

 BlocBuilder<AddBloc, AddState>(
  buildWhen: (previous, current) {
    // code is ommited
  },
  builder: (context, state) {
    if (state is ExpensesLoaded || state is CategoryChanged) {
      // code is ommited
    } else if (state is ExpensesLoading) {
      return getProgressSpinner();
    } else if (state is AddInitial) {
      // is it ok? If it's antipattern please give an advise how to do it correctly
      context.bloc<AddBloc>().add(CategoryChange([category]));
      return getProgressSpinner();
    } else {
      print('Bloc Loaded. Nothing to show inside Month Expenses...');
      return Container();
    }
  }
  

Вопрос о context.bloc<AddBloc>().add(CategoryChange([category])); . Это антипаттерн? Как это должно быть сделано?

Кстати, когда это выглядит так. В следующий раз, когда я добавлю CategoryChange событие в блок (которое даст CategoryChanged состояние), конструктор сверху по какой-то причине не реагирует…

Спасибо!

Я использую Flutter 1.22.3, flutter_bloc: 6.1.0

Ответ №1:

Как это должно быть сделано?

Когда вы знаете начальное состояние своего блока при его создании (скажем, статический список с первой записью, предварительно выбранной по умолчанию), вы можете использовать конструктор блока, который принимает это начальное состояние в качестве параметра.

Если вы не знаете, каково правильное начальное состояние, потому что оно динамическое (скажем, список местоположений, загруженных из сервиса на основе GPS, который пользователь должен согласиться получить нажатием кнопки, потому что это стоит денег), тогда вполне нормально иметь «пустой» или «неинициализированный» или состоянием «waitingForUserInteraction». В конце концов, тогда это состояние вашей программы.

Кстати, когда это выглядит так. В следующий раз, когда я добавлю событие CategoryChange в блок (что приведет к изменению состояния CategoryChanged), конструктор сверху по какой-то причине не реагирует

Блок определяет, следует ли отправлять новое изменение состояния, сравнивая старое и новое состояние. Если вы хотите изменить поведение по умолчанию, вы можете убедиться, что два состояния сравниваются как равные (или нет). Самый простой способ сделать это — получить ваши состояния из Equatable в пакете, приравниваемом следующим образом:

 @immutable
abstract class SomeState extends Equatable {
  final String importantChange;
  final String unimportantChange;

  const SomeState(this.importantChange, this.unimportantChange);

  @override
  List<Object> get props => [importantChange]; 
}
  

Только перечисление одного поля в списке «реквизит» означает, что только это сравнивается при сравнении на равенство. Если importantChange равно, состояния считаются равными (и не будут выдаваться из блока). Два состояния, имеющие одинаковые importantChange , но разные unimportantChange , считаются одинаковыми.

Комментарии:

1. Спасибо. Здесь немного другая логика. На самом деле это смесь всего, что вы написали. Я хочу показать экран с несколькими завершенными виджетами, и один виджет запустится с загрузчиком (в то же время будет запущен запрос БД). После того, как db ответит, соответствующий виджет должен быть обновлен