我正在学习Flutter 翼和积木图案从积木图书馆.我想我差不多理解了TODO的例子,但我正试图在它的基础上做一些稍微复杂一点的事情,但我遇到了困难.

所以,我的问题是.让我们考虑一下TODO示例https://bloclibrary.dev/#/fluttertodostutorial

与该页面上的GIF动画(可能已过时)所代表的情况相反,当你点击待办事项时,你不会进入"待办事项详细信息"页面,然后你可以转到"编辑待办事项"页面.您只需一步即可直接进入编辑页面:

Todo list -> Edit todo

我想要做的是让动画中可以看到的"两步走"流程:

Todo list -> Todo details -> Edit todo

因此,在代码中,实际的"一步"流是这样工作的:当您单击一个待办事项时,您将被带到EditTodoPage,它有自己的EditTodoBloc.此块使用您单击的待办事项进行初始化,但以一种"简单"的方式,只需传递待办事项(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是唯一更新待办事项的位置,因此它可以只有自己的状态.然后,当保存TODO时,它被保存在存储库中,并且您将被带回列表,该列表通过存储库、流和一切进行react .

但您将如何调整它以适应"两步走"的流程?天真的解决方案可能是对两个页面使用相同的BLOC,但为了便于讨论(因为每页有一个BLOC似乎是一种良好的做法),我们假设详细信息页面需要一个TodoDetailsBloc,编辑页面需要一个EditTodoBloc.在编辑页面上所做的编辑现在必须反映在详细信息页面上,所以我们不能只是天真地将TODO模型传递给模块.

这两个块是否应该监听来自存储库的新流?一条只会返回特定TODO的流?我不确定如何以及何时创建该流,以及它的生命周期是什么;我也不确定这样做是否与存储库有关.或者,这两个集团是否应该通过活动直接相互沟通?但对我来说,这似乎扰乱了良好的自上而下的存储库-块-小部件数据流.

那么,这在实践中会是什么样子呢?

或者,如果你有一个好的例子,一个(稍微)复杂的应用程序,我可以研究,我也很乐意接受.

谢谢:)

推荐答案

这些固执己见的问题是设计 Select 的一部分,在很大程度上取决于你试图实现的目标.以下只是我的观点:

  1. TODO示例似乎使整个软件体系 struct 变得臃肿(对于一个非常简单的应用程序),只是为了演示如何在代码库中的任何地方应用块模式.
  2. But how would you adapt that to work with the "two-step" flow?我甚至不会为TODO创建多个区块.仅一个具有多个TodoEvent(AddTodoEvent、EditTodoEvent、DeleteTodoEvent等)的TodoBloc就足够了.拥有更多的区块和活动只会带来更多的样板.
  3. (and because it seems to be a good practice to have one Bloc per page).不怎么有意思.一个块应该包含与一个业务逻辑相关的所有内容(因此称为BLOC=业务逻辑组件).你想把哪个商业逻辑联合成一个集团,哪个你宁愿拆分,这完全由你决定.但这类决策应该取决于业务逻辑本身,用户界面或应用程序的其他层都不应影响它们.在本例中,我会将TODO视为一个块.
  4. 有几种方法可以解决这个问题.TodoDetailsPage总是可以请求最新版本的ToDo.另一种方法是在编辑页中使用TodoDetailsBloc和EditTodoBloc.有单独的区块并不意味着你不能在一个页面上与多个区块交谈.
  5. Should the two Blocs listen to a new stream from the repository? A stream that would only return that particular Todo?并非如此,因为返回新编辑的TODO不应该是存储库的工作.存储库仅用于保存、更新和删除事务.
  6. Or maybe should the two Blocs communicate to each other directly via events?分根本不是.集团应该始终独立工作.如果您真的认为两个或更多个应该相互通信,那么您应该考虑将它们合并为一个区块.

我希望我能帮到你.请记住,这些答案更多的是基于意见.答案没有对错之分.

Flutter相关问答推荐

Flutter -如何从布局填充(对称水平)中排除小部件?

如何在Flutter 屏幕中添加箭头形状

从Flutter应用程序解释蓝牙BLE数据:了解Sylvania压力值

为什么Flutter 翼扩展卡有上下边框?

如何在容器小部件中的图像旁边添加文本?

如何将assets资源 实体类型转换为文件类型?

将侧边菜单和底部导航栏放在同一Flutter 应用程序中

在创建显示此错误的Flutter 深度链接时

了解多Provider 和流

Flutter:在 pubspec.yaml 中找不到assets资源

有没有办法在 google_map 上移动标记(向左或向右移动一些像素)?

在使用 Android 12+ 的真实 Android 设备上,SingleChildScrollView 中最初位于视口之外的无响应 Web 视图

为什么我们需要使用ChangeNotifierProvider而不是仅仅使用ChangeNotifier?

Flutter Firebase 升级后出现问题? ARC 语义问题 (Xcode): Select 器appleCredentialWithIDToken:rawNonce:fullName:没有已知的类方法

Flutter Dart 功能弹出错误的小部件?

java.lang.IncompatibleClassChangeError:找到接口 com.google.android.gms.location.SettingsClient,

如何在向下滚动时隐藏顶部卡片并在向上滚动时出现?

Flutter使Perspective Page View无限循环

根据索引/变量更改小部件的 colored颜色

检索 api 的值时,我得到_TypeError(类型'Null'不是'String'类型的子类型)