Блок — возможно ли выдавать состояния для предыдущей страницы в стеке навигации?

#flutter #dart #state #bloc #flutter-bloc

#flutter #dart #состояние #блок #flutter-bloc

Вопрос:

У меня есть blockbuilder, который обрабатывает создание виджетов в зависимости от полученного состояния для моей страницы панели мониторинга.

 body: BlocBuilder<DashboardBloc, DashboardState>(
        builder: (context, state) {
          print(state);
          if (state is DashboardInitial) {
            return loadingList();
          } else if (state is DashboardEmpty) {
            return emptyList();
          } else if (state is DashboardLoaded) {
            return loadedList(context, state);
          }
        },
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          Navigator.push(
              context, MaterialPageRoute(builder: (context) => AddPage()));
        },
  

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

 class AddPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    TextEditingController titleController = TextEditingController();
    TextEditingController descriptionController = TextEditingController();
    return Scaffold(
      appBar: AppBar(title: Text('Add')),
      body: Container(
        padding: EdgeInsets.all(10),
        child: Column(
          children: [
            TextField(
              controller: titleController,
            ),
            TextField(
              controller: descriptionController,
            ),
            RaisedButton(onPressed: () {
              BlocProvider.of<DashboardBloc>(context)
                  .add(DashboardWorryAdded('title', 'description'));
            }),
          ],
        ),
      ),
    );
  }
}
  

Следуя коду с использованием точек останова, я могу видеть, что мое состояние выводится в функции ‘mapeventtostate’, однако моя панель мониторинга никогда не перестраивается с новыми значениями.

Вот код для моего блока, событий и состояний. Моей первой мыслью было бы, что Equatable обнаруживает то же возвращаемое состояние, но после удаления Equatable моя проблема все еще сохраняется.

  @override
  Stream<DashboardState> mapEventToState(
    DashboardEvent event,
  ) async* {
    if (event is DashboardWorryAdded) {
      yield* _mapDashboardWorryAddedToState(event);
    } else if (event is DashboardLoading) {
      yield* _mapDashboardLoadingToState(event);
    } else if (event is AppStarted) {
      yield* _mapAppStartedToState(event);
    }
  }

  Stream<DashboardState> _mapAppStartedToState(AppStarted event) async* {
    List<Worry> _wList = await repo.getAllWorries();
    if (_wList.length != 0) {
      yield DashboardLoaded(worryList: _wList);
    } else {
      yield DashboardEmpty();
    }
  }

  Stream<DashboardState> _mapDashboardLoadingToState(
      DashboardLoading event) async* {
    List<Worry> _wList = await repo.getAllWorries();
    if (_wList != 0) {
      yield DashboardLoaded(worryList: _wList);
    } else {
      yield DashboardEmpty();
    }
  }

  Stream<DashboardState> _mapDashboardWorryAddedToState(
      DashboardWorryAdded event) async* {
    await repo.addWorry(event.title, event.description);
    List<Worry> worryList = List<Worry>();
    worryList = await repo.getAllWorries();
    yield DashboardLoaded(worryList: worryList);
  }
}
  
 @immutable
abstract class DashboardEvent {}

class DashboardLoading extends DashboardEvent {
  DashboardLoading();
}

class DashboardWorryAdded extends DashboardEvent {
  final String title, description;

  DashboardWorryAdded(this.title, this.description);
}

class AppStarted extends DashboardEvent {
  AppStarted();
}
  
 @immutable
abstract class DashboardState {}

class DashboardInitial extends DashboardState {
  DashboardInitial();
}

class DashboardLoaded extends DashboardState {
  final List<Worry> worryList;

  DashboardLoaded({this.worryList});
}

class DashboardEmpty extends DashboardState {
  DashboardEmpty();
}
  

Ответ №1:

Вместо того, чтобы пытаться изменить состояние другой страницы (немного нет-нет, когда речь идет об управлении состоянием), воспользуйтесь тем фактом, что push метод навигатора возвращает future, который завершается при открытии этой страницы, и в качестве бонуса значение future будет включать значениеэто было дано pop методу на другой странице. Итак, теперь вы можете сделать что-то вроде этого:

 class DashboardBloc {
  ...

  void showAddPage() async {
    // Do this to retrieve the value passed to the add page's call to `pop`
    final value = await Navigator.of(context).push(...);

    // Do this if the add page doesn't return a value in `pop`
    await Navigator.of(context).push(...);

    // Either way, you can now refresh your state in response to 
    // the add page popping
    emit(...);
  }
}
  

Примечание: это работает так же хорошо и для именованных маршрутов.

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

1. Похоже, это именно то, что мне было нужно. Я попробую завтра вечером и приму ваш ответ, как только он заработает. Спасибо!

2. Работает абсолютно идеально. Еще раз спасибо.