是否允许从一个集团内部将事件添加到另一个集团?

Posted

技术标签:

【中文标题】是否允许从一个集团内部将事件添加到另一个集团?【英文标题】:Is it allowed to add event to another bloc from inside of a bloc? 【发布时间】:2021-08-04 23:31:32 【问题描述】:

我正在使用 Dart 中提供的 bloc 库来实现“块”模式。我最终会转到flutter_bloc 库,这样我就可以在真正的应用程序中使用它了。

我有点难以理解如何创建一些可以从更专业的集团中调用的通用集团。专业化是指一些可能管理特定视图的集团。然后,通用集团将负责调用 API,甚至可能按顺序执行多项操作。

所以我的想法是,也许我有一个管理特定模型的StateA,因此我使用BlocA。每当将某个事件添加到BlocA 时,我还需要更新由BlocB 管理的StateB。我不想在同一个集团内这样做,因为这些不同的州包含可能不相关的不同数据。也许我可以让BlocC 用于应用程序的特定部分,但某些事件也应该调用BlocABlocB 中的事件和状态更改。

我正在考虑这样写BlocA bloc:

class BlocA extends BlocBase<BlocAEvent, BlocAState>  
  BlocA(BlocB blocB) : super(BlocAState()) 
    _blocB = blocB;
    _blocARepository = BlocARepository();
  ;

  BlocARepository _blocARepository;

  @override
  BlocAState mapEventToState(BlocAEvent event) async* 
    if (event is BlocAEventOne) 
      yield state.copyWith(valueOne: event.value);
     else if (event is BlocAEventTwo 
      // Get data related to BlocAState
      final data = await _blocARepository.fetchImportantData()
      // ! <-- I also need to fetch additional data but that is managed
      // by different bloc - BlocB
      _blocB.add(BlocBEventOne(id: data.id));
      yield state.copyWith(dataList: SomeModel.fromJSON(data));
    
  

然后像这样创建常规块BlocB

class BlocB extends BlocBase<BlocBEvent, BlocBState>  
  BlocB() : super(BlocBState()) 
    _blocBRepository = BlocBRepository();
  ;

  BlocBRepository _blocBRepository;

  @override
  BlocBState mapEventToState(BlocBEvent event) async* 
    if (event is BlocBEventOne) 
      // Get data related to BlocBState
      final data = await _blocBRepository.fetchOtherData(event.id)
      yield state.copyWith(dataList: SomeOtherModel.fromJSON(data));
    
  

我真的不确定这是否是正确的方法,因为基本上BlocA 添加了另一个事件。但我正在尝试做一些可重复使用的块并使数据更加独立。我知道我也可以在BlocA 中做_blocB.stream.listen,但这只会给我BlocB 集团的状态。我需要的是对某些事件做出反应的能力。

您是否认为我的方法可能很复杂,使用BlocObserver 可能更合适? BlocObserver 的问题是我不确定如何在 Flutter 应用程序中正确使用它。

【问题讨论】:

【参考方案1】:

您可以在您的事件中定义一个回调并在您的块中调用它,如下所示:

    blocA.add(BlocAEvent(whenDone: () 
      blocB.add(BlocBEvent())
    ));

【讨论】:

【参考方案2】:

首先,您要实现的目标完全没有问题,但让我们稍微谈谈架构。

一种选择可能是 BLoC B 订阅 BLoC A 状态更改并相应地处理它。例如,这里一个更具体的 BLoC 订阅了一个更通用的 BLoC 的更改:https://github.com/felangel/bloc/blob/master/examples/flutter_todos/lib/blocs/filtered_todos/filtered_todos_bloc.dart。为此,您需要稍微调整 BLoC A 状态(以便您可以识别此特定更改/事件),这可能不是可行的方法。

您应该考虑的另一件事是您是否要紧密耦合您的 BLoC(在您的示例中,BLoC B 引用通过构造函数传递给 BLoC A)。为此,您可以创建某种使用内部流的中介类: BLoC A 可以将事件发布到该中介类接收器,并且所有订阅者都将通过公开的流接收它(在您的情况下 - BLoC B 应该订阅该流) - 所以那里的通信就像 BLoC A -> Mediator -> BLoC B。这基本上就是 Mediator/Observer OOP 设计模式解决的问题。这样做的好处是您的 BLoC 不会相互了解任何信息,多个 BLoC 可以订阅多个不同的事件流,这意味着您可以随时为您的事件添加更多订阅者 (BLoC)。

【讨论】:

在这里操作。感谢您的回答,并感谢您提供的链接。听到这种行为没问题,我感到很欣慰。在某些情况下,我可以紧密耦合块,我认为可以将“通用”BLoC 传递给更专业的 BLoC(例如 BLoC 处理表单状态)。但实际上这取决于情况。我还认为,与其使用.stream.listen,不如实际使用onTransition 方法进行更精细的控制。顺便说一句,你有在 Dart bloc 库中实现的这种“中介”类的例子吗?这个中介类只是另一个 BLoC 吗? 我在这里用示例代码描述了中介者设计模式:mkobuolys.medium.com/… 和观察者:mkobuolys.medium.com/…

以上是关于是否允许从一个集团内部将事件添加到另一个集团?的主要内容,如果未能解决你的问题,请参考以下文章

寻找联想的新灵魂:以客户为导向

事件管理颤动集团模式

集团孵化型股权架构设计技巧

将附加要求纳入遗留数据库设计

启茗音乐娱乐集团宣布组织架构和人员调整,推动转型升级

反内卷!蚂蚁集团员工福利重磅升级!2千房补8点打车报销5天健康假10天育儿假......