как повторно использовать поля предыдущего состояния в шаблоне блока флаттера?

есть следующие. используя Sliding_up_panel, у которого есть тело с сообщениями и с другим представлением в содержании панели, которое появляется при нажатии кнопки из нижняя полоса.

  @override
  Stream<AppState> mapEventToState(
    AppEvent event,
  ) async* {
    if (event is LoadChat) {
      List<Msg> msgs = await Api.getMessages();
      yield LoadedChat(messages: msgs);
    } else if (event is OrderPanelOpen) {
      yield OpenedPanelState();
    } else if (event is OrderPanelClose) {
      yield ClosedPanelState();
    }
  }

Цель состоит в том, чтобы скрыть панель приложений при открытии панели. appBar присутствует в AppLayout, который является родителем, содержащим сам виджет SlidingUpPanel в Scaffold.

class _AppLayoutState extends State<AppLayout> {
  @override
  Widget build(BuildContext context) {
    var bloc = BlocProvider.of<AppBloc>(context);
    return Container(
      child: Scaffold(
        appBar: widget.showAppBar
            ? AppBar(...)
            : null,
        bottomNavigationBar: BottomAppBar(...),
        body: SlidingUpPanel(...),
      ),
    );
  }
}

Ниже приводится действие, которое добавляет события панели в блок.

 IconButton(
   icon: Icon(Icons.description),
   onPressed: () {
     if (widget.pannelCtrl.isPanelClosed()) {
       widget.pannelCtrl.open();
       bloc.add(OrderPanelOpen());
     } else {
       widget.pannelCtrl.close();
       bloc.add(OrderPanelClose());
     }
 })

Проблема здесь в том, что SlidingUpPanel имеет тело, которое должно отображать сообщения независимо от того, открыта или закрыта панель. Если события открытия и закрытия панели сопоставляются состояниям с помощью bloc, эти события открытия и закрытия должны быть отдельными состояниями, но сообщения из текущего состояния должны передаваться в новое состояние либо как параметры конструктора в новое состояние, либо другими способами. это правильный подход к достижению этого, или есть что-то еще более чистое, чего мне здесь не хватает.

class ClosedPanelState implements LoadedChat {
  final messagesArg;
  ClosedPanelState({this.messagesArg});

  @override
  Widget get currentView => Chat(messages: this.messagesArg);

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

  @override
  bool get showAppBar => true;

  @override
  String get title => 'Order Food';

  @override
  List<Msg> get messages => messages;
}

person Shanthakumar    schedule 17.12.2019    source источник
comment
Вы нашли подходящее решение ??   -  person Đặng Minh Hiếu    schedule 18.02.2021


Ответы (1)


Судя по названию вашего вопроса, вы можете кое-что сделать.

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

static final List<AppEvent> _events = new List<AppEvent>();

И в вашей реализации _mapEventToState добавьте события, вызываемые в переменную:

@override
  Stream<AppState> mapEventToState(
    AppEvent event,
  ) async* {
    _events.add(event); // New Line
    if (event is LoadChat) {
      List<Msg> msgs = await Api.getMessages();
      yield LoadedChat(messages: msgs);
    } else if (event is OrderPanelOpen) {
      yield OpenedPanelState();
    } else if (event is OrderPanelClose) {
      yield ClosedPanelState();
    }
  }

Позже вы напишете метод для вызова последнего события в стеке / списке.

dispatchPreviousState() {
    this.add(_events.removeLast());
  }

Это сработало для меня, чтобы вызвать последнее событие и снова отправить его.

person Andrés Escobar Pérez    schedule 25.03.2020