结合集团和Websocket

发布于 2025-02-03 05:57:57 字数 1100 浏览 4 评论 0原文

我正在尝试将BLOC与Websocket一起在两个方向上使用(即,当在Websocket上收到消息时,以及在发出状态发出的事件时,通过Web插座发送了一条消息)。我仍然是颤抖的新手,但已经用其他语言编写了类似的样式代码(消息队列和Websockets),但是我真的很努力地围绕着如何构造所有内容,以使其在扑朔迷离中起作用。

我有一个基本类,可以打开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()))
});

,但是这个听众永远不会开火。如果我将与小部件的孩子相同的代码放置,那么它可以正常工作,因此我假设blocklistener必须是小部件的孩子。

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

另外,是否有更好的方法可以构建代码,以便它可以访问Websocket和Bloc?

谢谢

I'm trying to use bloc with websockets in both directions (i.e. when a message is received on the websocket, an event is fired as well as when a state is emitted, a message is sent over the web socket). I'm still fairly new to flutter but have written similar style code (message queues and websockets) in other languages but and I'm really struggling to get my head around how to structure everything so it works in flutter.

I have a basic class that opens a websocket and waits for events

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));
      }
    );
  }
}

This works perfectly fine (although having to pass the BuildContext in feels a bit wrong). The issue is with listening for new states. I assumed I would be able to do something like this

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

However this listener never fires. If I place that same code as a child of a Widget then it works fine so I assume a BlockListener has to be a child of a widget.

My question is, is there a way of using BlocListener (or some alternative) without being a child of a widget?

Alternatively, is there a better way I could structure my code so it can have access to both the websocket and bloc?

Thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

倾`听者〃 2025-02-10 05:57:57

首先,blockListener必须是由bloc提供的小部件的孩子。

是的,我不会将buildContext传递到websocketmanager中。我会稍微翻转一下,以使其更干净。

当然,您的工作方式将取决于您的UI应基于事件和状态的行为。但是,为了使我的示例简单,我在下面有一个建议,其中一个小部件(也许是整个路线)是根据WebSocket消息侦听和更新的。您当然可以这样做,以便整个应用都受Websocket的影响,但这是“下一步”。

集团应该是您的WebSocketManager和UI之间的胶水。因此,我建议在适当的情况下(提供)将您的集团(提供)到小部件。该集团拥有websocketmanager的实例(也许是单身人士?)。在BLOC中具有一个方法和对应状态,该状态使用websocketmanager.connect()来设置连接。但是,而不是执行.... add(MessageCeived(msg))在收听回调中的内容,而是有一个方法(也许是您的connect()方法)返回stream&lt;类型msg&gt;,然后让收听回调屈服msg。然后,您可以在BLOC中设置streamSubscription websocketmanager的流,然后根据从Websocket收到的内容发射状态并根据收到的内容进行行动。

我建议您还将msg从侦听回程转换为您自己的域对象并在流中产生该域,以便您的集团不严格依赖于WebSocketManager的MSG类型。

这样,您的websocketmanager仅在数据层中执行'websocket-stuff',然后让bloc在应用程序层中执行逻辑,而用bloc emits则将UI更新允许UI更新。

First, the BlockListener must be a child of the widget being provided with the bloc.

Yeah, I wouldn't pass the BuildContext into the WebsocketManager. I'd flip it around a bit, to make it a bit cleaner.

How you do it will of course depend on how your UI should behave based on events and states. But for the sake of keeping my example simple, I have a suggestion below where a Widget (perhaps an entire route), is listening and updating based on the websocket messages. You can of course do it so that entire app is affected by the websocket, but that is "the next step".

The bloc should be the glue between your WebsocketManager and the UI. So I'd suggest to let your Bloc be created (provided) to a Widget where appropriate. The bloc holds an instance of WebsocketManager (perhaps a Singleton?). Have a method and corresponding state in the bloc that sets up the connection using WebsocketManager.connect(). But instead of doing the ....add(MessageReceived(msg)) stuff in the listen callback, have a method (perhaps it is your connect() method) that returns a Stream<type of msg> and let the listen callback yield msg. You can then in your bloc set up a StreamSubscription for the WebsocketManager's stream, and then emit states and act based on what is received from the websocket.

I'd suggest that you also convert the msg from the listen-callback to your own domain object and yield that in the stream, so that your bloc isn't strictly dependent on the msg type from the WebsocketManager.

This way your WebsocketManager only do 'websocket-stuff' in the data layer, and you let your bloc do the logic in the application layer, which in terms will let your UI update based on what you bloc emits.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文