我用的是flutter_bloc包.如果我有一个状态为widget列表的bloc,这是一种不好的做法吗?

每次我按下或弹出,我都会发出一种新的状态.这个bloc很有用,因为这样我可以在弹出窗口中显示的小部件/小屏幕中的任何位置调用push或pop.请让我知道我的用例是否清楚,或者您是否需要进一步的详细信息.谢谢

以下是相关代码:

自定义堆栈:

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);
}

堆栈块:

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小部件(您将看到我使用"state.last"的地方):

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();
          },
        );
    }
  }
}

这些类只是为那些想了解更多实现的人准备的,但是它们不应该有任何问题.问题更多的是关于处理这个用例的正确方法是什么.

推荐答案

将小部件放在一个组中是一种不好的做法.您的bloc不应该包含任何小部件和从Flutter框架导入的内容.一个集团应该只有Dart代码,并且保持平台/环境独立.

这是集团架构的第一条规则,也是谷歌工程师开发它的原因.他们试图将相同的业务逻辑代码用于Flatter和AngularDart应用程序,并提出了BloC架构.

查看关于bloc架构的链接:https://bloclibrary.dev/#/architecture

Flutter相关问答推荐

底部导航栏项目在抖动中不更改 colored颜色

更改BottomNavigationBar onTap?的大小

SingleChildScrollView在ErrorWidget.builder中不工作

如何将带有参数的函数传递给FIFTH中的自定义小部件

我如何在Android 13中通过Flutter应用程序打开文件(不是图像、视频或音频)?

Flutter Xcode 15 错误(Xcode):DT_TOOLCHAIN_DIR 无法用于判断 LIBRARY_SEARCH_PATHS

Flutter:我的应用程序是否需要包含退款购买?

Dart/Flutter 泛型:类型 '(SearchFilterItemModel) => String' 不是类型 '(SearchFilterItemModel) => String' 的子类型

Flutter如何在容器外创建环形进度条

Flutter: pie_chart 插件动画滚动问题

使用堆栈的自定义按钮

如何在 Flutter (iOS) 中解决这个问题

如何制作flutter showDialog、AlertDialog屏障 colored颜色 渐变

如何从底部导航栏打开 bottomModal 表?

如何为文本主题设置多种 colored颜色 ?

Flutter - 根据从第一个 DropdownButtonForm 中 Select 的内容在第二个 DropdownButton 上显示选项

在向 Google Route API 发送 HTTP Post 请求期间发生错误,

flutter - 无法解析 JSON 消息:文档为空

Future.wait() 中的 futures 可以顺序调用吗?

使用 Firebase/Flutter 进行应用判断 - 100% 无效请求