Flutter BLoC - Bloc vs Cubit事件驱动状态管理的优势

3

Bloc相较于Cubit的实际优势是什么?

除了可追踪性(你也可以通过适当的Cubit日志记录实现),以及高级事件转换(我想不出任何“高级”事件转换Cubit无法完成的,因为总有一种方法可以在Cubit中完成。如果使用干净的架构,领域/数据层可以帮助处理复杂的数据操作)。

共享和获取事件

这些是我希望能够通过Bloc实现的功能,因为这些功能在Cubit中无法实现。然而,这似乎是不可能的(还是说可以实现?)因为向Bloc添加事件需要识别将事件添加到的实际Bloc。bloc.add(YourEvent())

此外,事件共享有争议,因为这可能会导致糟糕的架构/难以维护。

对于事件溯源,我在文档中找不到是否支持此功能(返回到特定的过去状态?)。

我错过了什么吗?

3个回答

4
据我所知,无论是使用bloc还是cubit,只要拥有不可变状态,就可以轻松地将其恢复到过去的状态。拥有不可变状态可以让您存储状态列表,并在需要特定状态时进行恢复。
Cubit没有比bloc更多的优势,而是有不同的目的。在cubit中,您有action=>response(function=>states),而在bloc中,您有streams。
例如,当使用bloc(since bloc 7.20)时,可以同时处理两个事件,但在cubit上不能同时调用两个函数。
您可以在不同的bloc之间共享事件实现,因为必须指定bloc实现了哪些事件。
class MyBlocA extends Bloc<MyEvents, StatesA>

class MyBlocB extends Bloc<MyEvents, StatesB>

如果我理解正确,您想要做的是在两个不同的块中处理一个单独的事件,但是您无法这样做,因为事件被发射到特定的块。因此需要进行两次调用:
blocA.add(EventA);
blocB.add(EventA);

根据您的情况,您可能需要在MyBlocB内部监听MyBlocA的状态。这样,每当MyBlocB出现事件时,操作将取决于MyBlocA的状态。

1
我认为并发是Cubit在7.20之前可以做到而Bloc无法做到的,因为你只需要调用两个方法,它们就会同时处理。7.20也支持Bloc的并发。(这也在链接中提到了)。如果我只是要调用需要对事件进行操作的bloc,那么共享事件也不是优势,因为你也可以调用多个cubit函数。它们也不具有良好的可扩展性,因为每次在同一事件上添加新的bloc时,都需要调用新的bloc(s)。 - Tenten Ponce
1
既然你说它们是不可变的,我认为恢复先前状态对它们两个都有好处。考虑到不同的目的,而不是让 bloc 占优势于 cubit,可能是正确的方法。最后,我认为直接从 bloc 中监听 bloc 并不好,因为整体而言,这是一种糟糕的架构。 - Tenten Ponce
1
这是很棒的信息。该库的Github repo也建议你“从Cubit开始,直到需要重构为Bloc”。我现在已经将这个建议作为很多项目的经验法则,而且它对我非常有用。不要害怕重构,软件开发通常与此紧密相关,并且改进它通常意味着你会做一些重构。 - Alejandro
关于 Bloc 之间的通信,我理解您的偏好,因为我以前也是这样想的。但当我开始注意到有时您可能需要从一个 Bloc 中获取状态信息到另一个独立的 Bloc 时,我改变了我的想法。其中一个例子可能是在像 ProfileBloc 这样的单独的 bloc 中需要从 AuthBloc 获取 user。当然,您可以通过访问提供 ProfileBloc 时的上下文来发送状态,但是如果您的操作更改了 AuthBloc 中的 user 状态和 ProfileBloc 中的 user 状态之间可能会遇到同步问题。 - Alejandro

1

BlocCubit在状态管理方面是相同的,唯一的区别是状态变化的方式:Bloc是事件驱动的,而Cubit是方法驱动的。

除此之外,在架构方面目前没有太大差异。所有其他细节都已经被@chris准确地提到了。如何以可管理的方式维护状态取决于开发人员。


我同意,我正在寻找一个扎实的理由来使用Bloc的事件驱动设计,而不仅仅是出于个人偏好,因为对于新开发人员来说,这种设计更难以理解和学习。也许我会继续寻找答案。顺便说一句,谢谢。 - Tenten Ponce
我自从一年半以前就成为了一个狂热的BLoC用户。我从未使用过Cubit。在使用方面,我们两个是南辕北辙的。我一直是一个异步事件驱动的人,所以我理解你为什么在寻找答案。我希望你能找到最好的答案,一个适合你使用的答案。 - Ariel

0

事件不是用于依赖注入吗?

Cubit

  1. 调用Action
  2. 设置State

Bloc

  1. 触发Event(根据屏幕/页面触发时注入某些内容,例如)
  2. 然后调用Action
  3. 并设置State

1
我认为依赖注入在这里并不相关,事件驱动编程就像一个队列系统,由消费者处理。视图中的事件被排队(被发射),然后 bloc 类根据事件做出响应。 - Tenten Ponce

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接