如果我的集团的状态是小部件的列表,那是不好的做法吗?

发布于 2025-02-01 02:50:56 字数 5703 浏览 3 评论 0原文

我正在使用 flutter_bloc package。如果我有一个群体是小部件的列表,那是不好的做法吗? 我使用此集团从列表中推动(添加)和pop(删除)小部件/迷你屏幕。我使用此列表的弹出菜单的正文,该菜单具有类似嵌入式导航的东西。列表的最后一个成员是弹出案中显示的小部件。

每次我推出或弹出时,我都会发出一个新的状态。该集团很有用,因为这样我可以从弹出窗口显示的小部件/迷你屏幕中的任何地方调用推动或弹出。请让我知道我的用例是否清晰,或者您需要更多的详细信息。谢谢。

这是相关的代码片段:

自定义堆栈(其中e将是类型widget):

class PopoverStack<E> {
  PopoverStack() : _storage = <E>[];
  final List<E> _storage;

  void push(E element) {
    _storage.add(element);
  }

  void pop() {
    _storage.removeLast();
  }

  E get last => _storage.last;

  bool get isEmpty => _storage.isEmpty;

  bool get isNotEmpty => !isEmpty;

  PopoverStack.of(PopoverStack<E> stack) : _storage = List<E>.of(stack._storage);
}

堆栈的bloc(popoverPage是一个抽象类小部件将扩展):

class PopoverCardStackBloc extends Cubit<PopoverStack<PopoverPage>> {
  PopoverCardStackBloc(PopoverStack<PopoverPage> popoverStack) : super(popoverStack);

  void push(PopoverPage element) {
    emit(PopoverStack.of(state..push(element)));
  }

  void pop() {
    emit(PopoverStack.of(state..pop()));
  }
}

弹出式主体(在这里您会看到我使用state.lastwidget)的地方:

class PopoverCardBody extends StatelessWidget {
  const PopoverCardBody({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return BlocBuilder<PopoverCardStackBloc, PopoverStack<PopoverPage>>(
      builder: (context, state) {
        state;
        return Material(
          color: Colors.transparent,
          borderRadius: BorderRadius.circular(16),
          child: ClipRRect(
            borderRadius: BorderRadius.circular(16),
            child: AnimatedContainer(
              decoration: BoxDecoration(borderRadius: BorderRadius.circular(16)),
              height: state.last.height,
              width: 429,
              duration: const Duration(milliseconds: 200),
              curve: Curves.decelerate,
              child: Column(
                children: [
                  Container(
                    height: 72,
                    padding: const EdgeInsets.all(16),
                    color: AppColors.backgroundLight.withOpacity(.5),
                    child: CenteredTitleBar(
                      title: state.last.title,
                      leadingChild: GestureDetector(
                        behavior: HitTestBehavior.opaque,
                        onTap: state.last.showBackButton
                            ? () {
                                context.read<PopoverCardStackBloc>().pop();
                              }
                            : () {
                                BookingCard.tooltip.close();
                              },
                        child: state.last.showBackButton
                            ? const Icon(
                                Icons.chevron_left,
                                color: Colors.white,
                                size: 24,
                              )
                            : const Text(
                                'Close',
                                style: TextStyle(
                                  color: AppColors.textWhite,
                                  fontSize: 16,
                                  fontWeight: FontWeight.w400,
                                ),
                              ),
                      ),
                      trailingChild: _buildActionButton(context),
                    ),
                  ),
                  Expanded(
                    flex: 80,
                    child: Container(
                      width: double.infinity,
                      padding: const EdgeInsets.all(16),
                      child: state.last as Widget,
                    ),
                  )
                ],
              ),
            ),
          ),
        );
      },
    );
  }

  Widget _buildActionButton(BuildContext context) {
    switch (context.read<PopoverCardStackBloc>().state.last.editButtonType) {
      case StackActionButtonType.NONE:
        return const SizedBox.shrink();
      case StackActionButtonType.EDIT:
        return MockActionButton(
          labelPadding: const EdgeInsets.only(right: 16, left: 16, top: 7, bottom: 9),
          backgroundColor: AppColors.accentButton,
          borderRadius: BorderRadius.circular(8),
          splashColor: AppColors.transparent,
          label: 'Edit',
          textStyle: const TextStyle(
            color: AppColors.textWhite,
            fontSize: 16,
            fontWeight: FontWeight.w600,
          ),
          onTap: () {
            context.read<PopoverCardStackBloc>().push(const EditReservationPage());
          },
        );
      case StackActionButtonType.SAVE:
        return MockActionButton(
          labelPadding: const EdgeInsets.only(right: 16, left: 16, top: 7, bottom: 9),
          backgroundColor: AppColors.accentButton,
          borderRadius: BorderRadius.circular(8),
          splashColor: AppColors.transparent,
          label: 'Save',
          textStyle: const TextStyle(
            color: AppColors.textWhite,
            fontSize: 16,
            fontWeight: FontWeight.w600,
          ),
          onTap: () {
            //TODO: make request with PopoverEditCardStackBloc state to update booking when api is ready.
            BookingCard.tooltip.close();
          },
        );
    }
  }
}

这些类只是想了解的人方法更重要,但是它们应该没有什么错。问题更多是关于解决所述用例的正确方法是什么。

I am using flutter_bloc package. Is it a bad practice if I have a bloc whose state is a list of widgets?
I use this bloc to push (add) and pop (remove) widgets/mini-screens from a list. I use this list the body of a popup menu, which has something like an embedded navigation. The last member of the list is the widget that is displayed in the popover.

Every time I push or pop, I emit a new state. The bloc is useful since that way I can call push or pop from anywhere in the widgets/mini-screens I display in my popover. Please let me know if my use-case is clear or if you need further details. Thanks.

Here are the relevant pieces of code:

Custom stack (where E will be of type Widget):

class PopoverStack<E> {
  PopoverStack() : _storage = <E>[];
  final List<E> _storage;

  void push(E element) {
    _storage.add(element);
  }

  void pop() {
    _storage.removeLast();
  }

  E get last => _storage.last;

  bool get isEmpty => _storage.isEmpty;

  bool get isNotEmpty => !isEmpty;

  PopoverStack.of(PopoverStack<E> stack) : _storage = List<E>.of(stack._storage);
}

Bloc for stack (PopoverPage is an abstract class widgets will extend):

class PopoverCardStackBloc extends Cubit<PopoverStack<PopoverPage>> {
  PopoverCardStackBloc(PopoverStack<PopoverPage> popoverStack) : super(popoverStack);

  void push(PopoverPage element) {
    emit(PopoverStack.of(state..push(element)));
  }

  void pop() {
    emit(PopoverStack.of(state..pop()));
  }
}

Popover body (here you'll see places where I use state.last as Widget):

class PopoverCardBody extends StatelessWidget {
  const PopoverCardBody({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return BlocBuilder<PopoverCardStackBloc, PopoverStack<PopoverPage>>(
      builder: (context, state) {
        state;
        return Material(
          color: Colors.transparent,
          borderRadius: BorderRadius.circular(16),
          child: ClipRRect(
            borderRadius: BorderRadius.circular(16),
            child: AnimatedContainer(
              decoration: BoxDecoration(borderRadius: BorderRadius.circular(16)),
              height: state.last.height,
              width: 429,
              duration: const Duration(milliseconds: 200),
              curve: Curves.decelerate,
              child: Column(
                children: [
                  Container(
                    height: 72,
                    padding: const EdgeInsets.all(16),
                    color: AppColors.backgroundLight.withOpacity(.5),
                    child: CenteredTitleBar(
                      title: state.last.title,
                      leadingChild: GestureDetector(
                        behavior: HitTestBehavior.opaque,
                        onTap: state.last.showBackButton
                            ? () {
                                context.read<PopoverCardStackBloc>().pop();
                              }
                            : () {
                                BookingCard.tooltip.close();
                              },
                        child: state.last.showBackButton
                            ? const Icon(
                                Icons.chevron_left,
                                color: Colors.white,
                                size: 24,
                              )
                            : const Text(
                                'Close',
                                style: TextStyle(
                                  color: AppColors.textWhite,
                                  fontSize: 16,
                                  fontWeight: FontWeight.w400,
                                ),
                              ),
                      ),
                      trailingChild: _buildActionButton(context),
                    ),
                  ),
                  Expanded(
                    flex: 80,
                    child: Container(
                      width: double.infinity,
                      padding: const EdgeInsets.all(16),
                      child: state.last as Widget,
                    ),
                  )
                ],
              ),
            ),
          ),
        );
      },
    );
  }

  Widget _buildActionButton(BuildContext context) {
    switch (context.read<PopoverCardStackBloc>().state.last.editButtonType) {
      case StackActionButtonType.NONE:
        return const SizedBox.shrink();
      case StackActionButtonType.EDIT:
        return MockActionButton(
          labelPadding: const EdgeInsets.only(right: 16, left: 16, top: 7, bottom: 9),
          backgroundColor: AppColors.accentButton,
          borderRadius: BorderRadius.circular(8),
          splashColor: AppColors.transparent,
          label: 'Edit',
          textStyle: const TextStyle(
            color: AppColors.textWhite,
            fontSize: 16,
            fontWeight: FontWeight.w600,
          ),
          onTap: () {
            context.read<PopoverCardStackBloc>().push(const EditReservationPage());
          },
        );
      case StackActionButtonType.SAVE:
        return MockActionButton(
          labelPadding: const EdgeInsets.only(right: 16, left: 16, top: 7, bottom: 9),
          backgroundColor: AppColors.accentButton,
          borderRadius: BorderRadius.circular(8),
          splashColor: AppColors.transparent,
          label: 'Save',
          textStyle: const TextStyle(
            color: AppColors.textWhite,
            fontSize: 16,
            fontWeight: FontWeight.w600,
          ),
          onTap: () {
            //TODO: make request with PopoverEditCardStackBloc state to update booking when api is ready.
            BookingCard.tooltip.close();
          },
        );
    }
  }
}

These classes are just here for the one who wants to understand the approach more, however there shouldn't be anything wrong with them. The question is more about what is the correct way to tackle the use case described.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

幸福不弃 2025-02-08 02:50:56

在集团中将小部件放在一个不好的习惯上。您的集团不应包含从颤音框架中的任何小部件和进口。集团应只有飞镖代码,并且独立于平台/环境。

这是集团体系结构的第一个规则,也是工程师在Google开发它的原因。他们试图将相同的业务逻辑代码用于Flutter和Angulardart应用程序,并提出集体体系结构。
您可以观看此视频,:)一切如何开始: https://www.youtube。 com/watch?v = kn0eos-ziic

并检查有关集体体系结构的链接: https:// bloclibrary。开发/#/架构

It is a bad practice to have widgets in a bloc. Your bloc should not contain any widgets and imports from the Flutter framework. A bloc should only have Dart code and remain platform/environment independent.

This is the first rule of bloc architecture and the reason why engineers develop it at Google. They were trying to use the same business logic code for both Flutter and AngularDart apps and came up with BloC architecture.
You can watch this video, :) how it all started: https://www.youtube.com/watch?v=kn0EOS-ZiIc

And check this link about bloc architecture: https://bloclibrary.dev/#/architecture

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文