我正在从 Bloc 库学习 Flutter 和 BLoC 模式。我想我刚刚理解了 Todo 示例,但我试图在它的基础上做一些更复杂的事情,但我遇到了困难。
所以,我的问题是这样的。让我们考虑一下 Todo 示例 https://bloclibrary.dev/#/fluttertodostutorial
与该页面上的(可能已经过时的)GIF 动画所表示的相反,当您单击待办事项时,您不会进入“待办事项详细信息”页面,然后可以从该页面转到“编辑待办事项”页。您只需一步即可直接进入编辑页面:
Todo list -> Edit todo
我想做的是获得动画中可以看到的“两步”流程:
Todo list -> Todo details -> Edit todo
因此,在代码中,实际的“一步”流程是这样工作的:当您单击待办事项时,您将被带到 EditTodoPage,它有自己的 EditTodoBloc。该 Bloc 使用您单击的待办事项进行初始化,但以“简单”的方式进行,只需传递待办事项的模型 (initialTodo
)。
// in EditTodoPage
static Route<void> route({Todo? initialTodo}) {
return MaterialPageRoute(
fullscreenDialog: true,
builder: (context) => BlocProvider(
create: (context) => EditTodoBloc(
todosRepository: context.read<TodosRepository>(),
initialTodo: initialTodo,
),
child: const EditTodoPage(),
),
);
}
这意味着 EditTodoBloc 不会对待办事项的更改做出“ react ”。这是有效的,因为 EditTodoPage 是更新待办事项的唯一位置,因此它可以有自己的状态。然后,当保存待办事项时,它会保存在存储库中,然后您将返回到列表,该列表通过存储库和流以及所有内容进行 react 。
但是您将如何调整它以适应“两步”流程?天真的解决方案可能是对两个页面使用相同的 Bloc,但为了论证(并且因为每页使用一个 Bloc 似乎是一种很好的做法),假设我们想要一个用于详细信息页面的 TodoDetailsBloc 和一个EditTodoBloc 用于编辑页面。现在,在编辑页面上进行的编辑必须反射(reflect)在详细信息页面上,因此我们不能只是天真地将待办事项模型传递给区 block 。
这两个 Bloc 是否应该监听存储库中的新流?一个只会返回特定 Todo 的流?我不确定该流将如何以及何时创建以及它的生命周期是什么;我不确定存储库是否关心这样做。或者也许两个 Bloc 应该通过事件直接相互沟通?但对我来说,这似乎破坏了良好的自上而下的存储库 block 小部件数据流。
那么,在实践中会是什么样子?
或者,如果您有一个(稍微)更复杂的应用程序的好例子可供我研究,我也很乐意接受。
谢谢:)
最佳答案
这些固执己见的问题是设计选择的一部分,并且在很大程度上取决于您想要实现的目标。以下仅代表我的观点:
- Todo 示例似乎使整个软件架构变得臃肿(对于一个非常简单的应用程序),只是为了演示如何在代码库中的任何地方应用 bloc 模式。
- 但是您如何调整它以适应“两步”流程?我什至不会为 Todo 创建多个 block 。只需一个具有多个 TodoEvents(AddTodoEvent、EditTodoEvent、DeleteTodoEvent,...)的 TodoBloc 就足够了。拥有更多的区 block 和事件只会导致更多的样板文件。
- (因为每页有一个 Bloc 似乎是一种很好的做法)。并不真地。一个 block 应该包含与一个业务逻辑相关的所有内容(因此名称 BLoC = 业务逻辑组件)。这完全取决于您想要将哪些业务逻辑联合为一个整体以及您希望拆分哪些业务逻辑。但此类决策应取决于业务逻辑本身,UI 或应用程序的其他层都不应影响它们。对于这个例子,我将把 Todo 视为一个整体。
- 现在,在编辑页面上进行的编辑必须反射(reflect)在详细信息页面上,因此我们不能简单地将待办事项模型传递给区 block 。有多种方法可以解决此问题。 TodoDetailsPage 始终可以请求最新版本的 Todo。另一种方法是在编辑页面中使用 TodoDetailsBloc 和 EditTodoBloc。拥有单独的区 block 并不意味着您不能在一个页面上与多个区 block 交谈。
- 两个 Bloc 是否应该监听存储库中的新流?一个只会返回特定 Todo 的流? 事实并非如此,因为返回新编辑的 Todo 不应该是存储库的工作。存储库仅用于保存、更新和删除交易。
- 或者也许两个 Bloc 应该通过事件直接相互通信?完全不可以。 Bloc 应该始终独立运作。如果您确实认为两个或多个应该相互通信,那么您应该考虑将它们合并为一个 Bloc 。
我希望我能帮到你。请记住,这些答案更多地基于意见。答案没有正确和错误之分。
关于Flutter Bloc Todo 示例 - 监听存储库中的单个待办事项,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73709769/