我试图在两个方向上使用websockets(即,当websocket接收到消息时,触发事件以及当状态发出时,通过websocket发送消息)。我对flutter还很陌生,但是用其他语言写过类似风格的代码(消息队列和websockets),但是我真的很努力地想知道如何构建一切,以便它在flutter中工作。
我有一个基本类打开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
in感觉有点错误)。问题在于倾听新出现的州。我认为我可以做这样的事情
BlocListener<SomeBloc, SomeState>(
listener: (context, state) {
if(!sendMessage(SomeMessage()))
});
但是这个监听器永远不会触发。如果我将相同的代码作为Widget的子组件,那么它就可以正常工作,所以我假设BlockListener
必须是Widget的子组件。
我的问题是,有没有一种方法使用BlocListener(或一些替代方案),而不是一个小部件的孩子?
或者,有一个更好的方法,我可以结构我的代码,使它可以访问websocket和集团?
感谢首先,BlockListener
必须是与块一起提供的小部件的子组件。
是的,我不会传递BuildContext到WebsocketManager
。我会把它翻转一下,让它更干净一点。
块应该是你的WebsocketManager
和UI之间的粘合剂。因此,我建议让您的Bloc在适当的地方创建(提供)到一个Widget。该集团持有一个WebsocketManager
的实例(可能是Singleton?)在使用WebsocketManager.connect()
建立连接的块中有一个方法和相应的状态。但是,不是在监听回调中做....add(MessageReceived(msg))
的事情,而是有一个方法(可能是您的connect()
方法)返回Stream<type of msg>
并让监听回调yield msg
。然后,你可以在你的模块中为WebsocketManager的流设置一个StreamSubscription
,然后根据从websocket接收到的内容发出状态并采取行动。
我建议你也将msg
从监听回调转换为你自己的域对象,并在流中产生它,这样你的块就不会严格依赖于WebsocketManager的msg类型。
这样你的WebsocketManager
只在数据层做'websocket-stuff',你让你的bloc在应用层做逻辑,这将让你的UI基于你的bloc发出的内容更新。