如果我的集团的状态是一个小部件列表,这是一种不好的做法吗?
Is it a bad practice if my bloc's state is a list of widgets?
我正在使用 flutter_bloc 包。如果我有一个状态是小部件列表的集团,这是一种不好的做法吗?
我使用此 bloc 从列表中推送(添加)和弹出(删除)widgets/mini-screens。我将此列表用作弹出菜单的主体,它具有类似于嵌入式导航的功能。列表的最后一个成员是弹出窗口中显示的小部件。
每次我按下或弹出时,我都会发出一个新状态。 bloc 很有用,因为这样我就可以从弹出窗口中显示的 widgets/mini-screens 中的任何位置调用 push 或 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);
}
堆栈块(PopoverPage
是一个抽象 class 小部件将扩展):
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.last
用作 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();
},
);
}
}
}
这些 class 只是为那些想要更多地了解该方法的人准备的,但是它们应该没有任何问题。问题更多是关于解决所描述用例的正确方法是什么。
将小部件放在一个块中是一种不好的做法。您的 bloc 不应包含任何小部件和来自 Flutter 框架的导入。一个集团应该只有 Dart 代码并保持 platform/environment 独立。
这是 bloc 架构的第一条规则,也是工程师在 Google 开发它的原因。他们试图为 Flutter 和 AngularDart 应用程序使用相同的业务逻辑代码,并提出了 BloC 架构。
您可以观看此视频,:) 这一切是如何开始的:https://www.youtube.com/watch?v=kn0EOS-ZiIc
并查看关于区块架构的 link:https://bloclibrary.dev/#/architecture
我正在使用 flutter_bloc 包。如果我有一个状态是小部件列表的集团,这是一种不好的做法吗? 我使用此 bloc 从列表中推送(添加)和弹出(删除)widgets/mini-screens。我将此列表用作弹出菜单的主体,它具有类似于嵌入式导航的功能。列表的最后一个成员是弹出窗口中显示的小部件。
每次我按下或弹出时,我都会发出一个新状态。 bloc 很有用,因为这样我就可以从弹出窗口中显示的 widgets/mini-screens 中的任何位置调用 push 或 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);
}
堆栈块(PopoverPage
是一个抽象 class 小部件将扩展):
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.last
用作 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();
},
);
}
}
}
这些 class 只是为那些想要更多地了解该方法的人准备的,但是它们应该没有任何问题。问题更多是关于解决所描述用例的正确方法是什么。
将小部件放在一个块中是一种不好的做法。您的 bloc 不应包含任何小部件和来自 Flutter 框架的导入。一个集团应该只有 Dart 代码并保持 platform/environment 独立。
这是 bloc 架构的第一条规则,也是工程师在 Google 开发它的原因。他们试图为 Flutter 和 AngularDart 应用程序使用相同的业务逻辑代码,并提出了 BloC 架构。 您可以观看此视频,:) 这一切是如何开始的:https://www.youtube.com/watch?v=kn0EOS-ZiIc
并查看关于区块架构的 link:https://bloclibrary.dev/#/architecture