简体   繁体   English

Flutter Bloc Todo 示例 - 收听存储库中的单个 todo

[英]Flutter Bloc Todo example - Listen to a single todo from the repository

I am learning Flutter and the BLoC pattern from the Bloc library.我正在学习 Bloc 库中的 Flutter 和 BLoC 模式。 I think I just about understand the Todo example, but I'm trying to build upon it to do something just a tad more complex, and I'm hitting a wall.我想我只是理解 Todo 的例子,但我正试图在它的基础上做一些更复杂的事情,而且我碰壁了。

So, my issue is this.所以,我的问题是这个。 Let's consider the Todo example https://bloclibrary.dev/#/fluttertodostutorial让我们考虑 Todo 示例https://bloclibrary.dev/#/fluttertodostutorial

Contrary to what the (probably outdated) GIF animation on that page is representing, when you click on a Todo, you don't get to a "Todo details" page from which you can then go to an "Edit todo" page.与该页面上的(可能已过时的)GIF animation 所代表的相反,当您单击待办事项时,您不会进入“待办事项详细信息”页面,然后您可以从中 go 到“编辑待办事项”页面。 You get directly to the edit page in a single step:您只需一步即可直接进入编辑页面:

Todo list -> Edit todo

What I'm trying to do is to have the "two-step" flow that can be seen in the animation:我想要做的是在 animation 中看到“两步”流程:

Todo list -> Todo details -> Edit todo

So, in the code, the actual "one-step" flow works like that: when you click on a todo, you are taken to the EditTodoPage, which has its own EditTodoBloc.因此,在代码中,实际的“一步”流程是这样工作的:当您单击一个待办事项时,您会被带到拥有自己的 EditTodoBloc 的 EditTodoPage。 This Bloc is initialized with the todo you clicked on, but in a "plain" way, just by passing the model of the todo ( initialTodo ).该 Bloc 使用您单击的 todo 进行初始化,但以“普通”方式,只需传递 todo 的 model ( 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(),
      ),
    );
  }

This means that EditTodoBloc is not "reactive" to changes to the todo.这意味着 EditTodoBloc 对待办事项的更改没有“反应性”。 This works because the EditTodoPage is the only place where the todo gets updated, so it can just have its own state.这是因为 EditTodoPage 是唯一更新 todo 的地方,所以它可以有自己的 state。 Then when the todo is saved, it is saved in the repository, and you are taken back to the list, which is reactive via the repository and stream and everything.然后当待办事项被保存时,它会保存在存储库中,然后您将返回到列表,该列表通过存储库和 stream 和所有内容进行响应。

But how would you adapt that to work with the "two-step" flow?但是你将如何调整它以适应“两步”流程? The naive solution may be to use the same Bloc for both pages, but for the sake of argument (and because it seems to be a good practice to have one Bloc per page), let's say we want a TodoDetailsBloc for the details page and an EditTodoBloc for the edit page.天真的解决方案可能是对两个页面使用相同的 Bloc,但为了争论(并且因为每页有一个 Bloc 似乎是一种好习惯),假设我们想要一个 TodoDetailsBloc 用于详细信息页面和一个EditTodoBloc 用于编辑页面。 The edits made on the edit page must now be reflected on the details page so we can't just pass the todo model to the blocs naively.在编辑页面上所做的编辑现在必须反映在详细信息页面上,因此我们不能天真地将 todo model 传递给集团。

Should the two Blocs listen to a new stream from the repository?这两个集团是否应该从存储库中收听新的 stream ? A stream that would only return that particular Todo?一个 stream 只会返回那个特定的 Todo? I'm not sure how and when that stream would get created and what its lifecycle would be;我不确定 stream 将如何以及何时创建以及它的生命周期是什么; and I'm not sure it's the concern of the repository to do that.而且我不确定存储库是否关心这样做。 Or maybe should the two Blocs communicate to each other directly via events?或者也许这两个集团应该通过事件直接相互交流? But to me this seems to disrupt the nice top-down repository-bloc-widget data flow.但对我来说,这似乎破坏了自上而下的存储库块小部件数据流。

So, how would that look like in practice?那么,在实践中会是什么样子呢?

Or alternatively, if you have a good example of a (slightly) more complex app that I could study, I would gladly take that too.或者,如果你有一个我可以研究的(稍微)更复杂的应用程序的好例子,我也很乐意接受。

Thanks:)谢谢:)

These kind of opinionated questions are part of design choices and are heavily dependent on what you are trying to achieve.这些固执己见的问题是设计选择的一部分,并且在很大程度上取决于您要实现的目标。 The following is just my opinion:以下只是我的看法:

  1. It seems like the Todo example bloated up the whole software architecture (for a very simple app) just to demonstrate how you can apply the bloc pattern everywhere in your code base.看起来 Todo 示例膨胀了整个软件架构(对于一个非常简单的应用程序),只是为了演示如何在代码库中的任何地方应用 bloc 模式。
  2. But how would you adapt that to work with the "two-step" flow?但是你将如何调整它以适应“两步”流程? I would not even create multiple blocs for Todo.我什至不会为 Todo 创建多个区块。 Just one TodoBloc with multiple TodoEvents (AddTodoEvent, EditTodoEvent, DeleteTodoEvent, ...) is sufficient.只需一个带有多个 TodoEvents(AddTodoEvent、EditTodoEvent、DeleteTodoEvent,...)的 TodoBloc 就足够了。 Having more blocs and events only leads to more boilerplate.拥有更多的集团和事件只会导致更多的样板。
  3. (and because it seems to be a good practice to have one Bloc per page) . (并且因为每页有一个 Bloc 似乎是一个好习惯) Not really.并不真地。 A bloc should contain everything which is related to one business logic (hence the name BLoC = Business Logic Component).一个块应该包含与一个业务逻辑相关的所有内容(因此名称 BLoC = 业务逻辑组件)。 It's totally up to you which business logic you want to unite as one bloc and which you rather want to split up.您希望将哪个业务逻辑合并为一个集团,以及您希望拆分哪个业务逻辑,这完全取决于您。 But these kind of decisions should be dependent on the business logic itself, neither UI nor other layers of your application should influence them.但是这些决策应该依赖于业务逻辑本身,UI 和应用程序的其他层都不应该影响它们。 For this example I would consider Todo as one bloc.对于这个例子,我会将 Todo 视为一个整体。
  4. The edits made on the edit page must now be reflected on the details page so we can't just pass the todo model to the blocs naively.在编辑页面上所做的编辑现在必须反映在详细信息页面上,因此我们不能天真地将 todo model 传递给集团。 There are several ways to solve this problem.有几种方法可以解决这个问题。 The TodoDetailsPage could always ask for the newest version of the Todo. TodoDetailsPage 总是可以要求最新版本的 Todo。 Another way would be to use TodoDetailsBloc along with EditTodoBloc inside the edit page.另一种方法是在编辑页面内使用 TodoDetailsBloc 和 EditTodoBloc。 Having separate blocs does not mean you are not allowed to talk to multiple blocs on one page.拥有单独的集团并不意味着您不允许在一页上与多个集团交谈。
  5. Should the two Blocs listen to a new stream from the repository?这两个集团是否应该从存储库中收听新的 stream ? A stream that would only return that particular Todo?一个 stream 只会返回那个特定的 Todo? Not really as it should not be the job of the repository to return the newly edited Todo.并非如此,因为返回新编辑的 Todo 不应该是存储库的工作。 The repository is only there to save, update and delete transactions.存储库仅用于保存、更新和删除事务。
  6. Or maybe should the two Blocs communicate to each other directly via events?或者也许这两个集团应该通过事件直接相互交流? Not at all.一点也不。 Bloc's should always work independently. Bloc应该始终独立工作。 If you really think that two or more should communicate to each other, then you should consider merging them into one bloc.如果您真的认为两个或更多应该相互通信,那么您应该考虑将它们合并为一个集团。

I hope I could help you with that.我希望我能帮助你。 Please keep in mind that these answers are more based on opinions.请记住,这些答案更多地基于意见。 There are no right and wrong answers.没有正确和错误的答案。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM