结合 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 更新基于你集团发出的东西。
我正在尝试在两个方向上将 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 更新基于你集团发出的东西。