如何在Flutter应用的多个屏幕中使用来自一个WebSocket连接的数据?

huangapple go评论56阅读模式
英文:

How to use Websocket data from one connection in multiple screens of a Flutter application?

问题

我正在构建一个Flutter应用程序,通过WebSocket连接从服务器接收实时数据。从服务器接收的数据与应用程序的所有屏幕相关。我想在应用程序的所有屏幕中使用这些数据,而不必在每个屏幕上都建立一个新的WebSocket连接。

如何实现这一点?是否有一种方法只建立一次WebSocket连接并在应用程序的所有屏幕中使用接收到的数据?我应该使用全局变量来存储接收到的数据,还是有更好的方法?

我正在使用web_socket_channel包来建立WebSocket连接,目前是通过Navigator小部件将接收到的数据传递给每个屏幕。然而,这种方法不具有可伸缩性,使代码难以维护。

关于如何实现这一功能的任何指导将不胜感激。

这是我用于初始化Socket连接的函数。

import 'package:web_socket_channel/io.dart';
import 'package:web_socket_channel/web_socket_channel.dart';

late WebSocketChannel webSocketChannel;

void connectWebSocket() {
  WebSocket.connect("wss://MY_DOMAIN_URL", headers: {
    'Connection': 'Upgrade',
    'Upgrade': 'WebSocket',
  }).then((ws) {
    log('SOCKET CONNECTED');
    // 创建流通道
    webSocketChannel = IOWebSocketChannel(ws);

    // webSocketChannel.stream.listen((message) {
    //   log(message);
    // });
  }).catchError((onError) {
    log('onError $onError');
  });
}

如果需要的话,我想在所有屏幕上使用message数据。

此外,我已经检查过StramBuilder,但在某些情况下,我也想在构建方法之外访问message数据。

英文:

I'm building a Flutter application that receives real-time data from a server via a Websocket connection. The data received from the server is relevant to all screens of the application. I want to use this data in all screens of the application, without having to establish a new Websocket connection on each screen.

How can I achieve this? Is there a way to establish the Websocket connection only once and use the data received in all screens of the application? Should I use a global variable to store the received data or is there a better approach?

I'm using the web_socket_channel package to establish the Websocket connection and I'm currently passing the received data to each screen using the Navigator widget. However, this approach is not scalable and makes the code difficult to maintain.

Any guidance on how to implement this feature would be highly appreciated.

Here is my function for the init socket connection.

    import 'package:web_socket_channel/io.dart';
    import 'package:web_socket_channel/web_socket_channel.dart';
    
    late WebSocketChannel webSocketChannel;
    
    void connectWebSocket() {
      WebSocket.connect("wss://MY_DOMAIN_URL", headers: {
        'Connection': 'Upgrade',
        'Upgrade': 'WebSocket',
      }).then((ws) {
        log('SOCKET CONNECCTED');
        // create the stream channel
        webSocketChannel = IOWebSocketChannel(ws);
    
        // webSocketChannel.stream.listen((message) {
        //   log(message);
        // });
    
    
      }).catchError((onError) {
        log('onError $onError');
      });
    }

I want to use message data on all the screens if necessary.

Also, I checked StramBuilder but in some cases, I also want to access message data outside of the build method.

答案1

得分: 1

以下是已翻译的部分:

有关此场景,取决于您选择的状态管理库,有一些方法。下面是一个方法的基本想法。我个人建议使用rxdart,因为它的Stream子类BehaviorSubject允许您访问Stream的最后一个发出的值,而无需订阅。基类Stream不提供这个很酷的功能。

假设我们有一个名为MessageService单例服务,我们将从webSocketChannel流中发出的值添加到_subject流中:

class MessageService {
  final _subject = BehaviorSubject<Message>();

  Stream<Message> get stream => _subject;
  Message get latest =>  _subject.value;

  void startListen() {
    // 设置 WebSocket
    webSocketChannel.stream.listen((data) {
      _subject.add(Message.parse(data));
    });
  }

  void stopListen() {}
}

您可以使用StreamBuilder小部件来监听messageService.stream,以便在新消息发出时在任何地方重新构建用户界面。使用messageService.latest来从任何地方访问最新消息。

英文:

There are some approaches to this scenario depending on what state managment library you choose.
Below are some basic ideas of one approach.
I personally recommend rxdart since its Stream-subclass BehaviorSubject lets you have access to the last emitted value of the Stream without having to subscribe. The base class Stream does not provide this cool feature.
Let's say we have a singleton service called MessageSerivce, we will add values emitted from the webSocketChannel stream to the _subject stream:

class MessageSerivce {
  final _subject = BehaviorSubject&lt;Message&gt;();

  Stream&lt;Message&gt; get stream =&gt; _subject;
  Message get latest =&gt;  _subject.value;

  void startListen() {
    // setup web socket
    webSocketChannel.stream.listen((data) {
      _subject.add(Message.parse(data));
    });
  }

  void stopListen() {}
}

You can use the StreamBuilder widget to listen to messageService.stream to rebuild UI anywhere when a new message is emitted.
Use messageService.latest to access the latest message from anywhere.

huangapple
  • 本文由 发表于 2023年2月24日 17:09:02
  • 转载请务必保留本文链接:https://go.coder-hub.com/75554581.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定