结合 bloc 和 websockets

Combining bloc and websockets

我正在尝试在两个方向上将 bloc 与 websocket 一起使用(即,当在 websocket 上收到消息时,将触发一个事件,以及当发出状态时,将通过 web 套接字发送消息) .我对 flutter 还是很陌生,但已经用其他语言编写了类似样式的代码(消息队列和 websockets),但我真的在努力了解如何构建所有内容以使其在 flutter 中工作。

我有一个基本的 class 打开 websocket 并等待事件

class WebsocketManager {
  final BuildContext context;
  late IOWebSocketChannel channel;

  WebsocketManager(this.context);

  void connect(){
    channel = IOWebSocketChannel.connect(Uri.parse(wsBaseUrl));
    channel.stream.listen(
      (msg) {
        //process msg 
        BlocProvider.of<SomeBloc>(context).add(MessageReceived(msg));
      }
    );
  }
}

这工作得很好(尽管必须传递 BuildContext 感觉有点不对劲)。问题在于监听新状态。我以为我可以做这样的事情

BlocListener<SomeBloc, SomeState>(
  listener: (context, state) {
    if(!sendMessage(SomeMessage()))
});

但是这个侦听器永远不会触发。如果我将相同的代码作为 Widget 的子项放置,那么它可以正常工作,所以我假设 BlockListener 必须是 Widget 的子项。

我的问题是,有没有一种方法可以使用 BlocListener(或其他替代方法)而不是小部件的子项?

或者,有没有更好的方法来构建我的代码,使其可以访问 websocket 和 bloc?

谢谢

首先,BlockListener 必须是随集团提供的小部件的子项。

是的,我不会将 BuildContext 传递到 WebsocketManager。我会把它翻转一下,让它更干净一些。

你如何做当然取决于你的 UI 根据事件和状态应该如何表现。但是为了让我的示例保持简单,我在下面提出了一个建议,其中 Widget(可能是整个路由)正在根据 websocket 消息进行侦听和更新。您当然可以这样做,以便整个应用程序都受到 websocket 的影响,但这是“下一步”。

集团应该是你的 WebsocketManager 和 UI 之间的粘合剂。因此,我建议在适当的时候将您的 Bloc 创建(提供)到 Widget。该集团持有 WebsocketManager 的实例(也许是单例?)。使用 WebsocketManager.connect() 建立连接的 bloc 中有一个方法和相应的状态。但是不要在监听回调中做 ....add(MessageReceived(msg)) 的事情,而是有一个方法(也许是你的 connect() 方法) returns a Stream<type of msg> 并让监听回调 yield msg。然后,您可以在您的集团中为 WebsocketManager 的流设置 StreamSubscription,然后发出状态并根据从 websocket 接收到的内容采取行动。

我建议您也将 msg 从 listen-callback 转换为您自己的域对象并在流中产生它,这样您的集团就不会严格依赖于味精从 WebsocketManager 中输入。

这样你的 WebsocketManager 只在数据层做 'websocket-stuff',你让你的 bloc 在应用层做逻辑,这会让你的 UI 更新基于你集团发出的东西。