结合集团和Websocket
我正在尝试将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 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
首先,
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 ofWebsocketManager
(perhaps a Singleton?). Have a method and corresponding state in the bloc that sets up the connection usingWebsocketManager.connect()
. But instead of doing the....add(MessageReceived(msg))
stuff in the listen callback, have a method (perhaps it is yourconnect()
method) that returns aStream<type of msg>
and let the listen callbackyield msg
. You can then in your bloc set up aStreamSubscription
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.