You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Dart使用SignalR获取Websocket数据渲染UI白屏问题咨询

Flutter 基于SignalR获取WebSocket数据渲染UI方案

现有代码问题

  • fetchGps方法固定返回null,FutureBuilder无法获取实际业务数据,Text组件默认渲染空字符串导致白屏
  • 仅通过invoke做单次方法调用,未注册服务端实时消息监听,无法接收WebSocket长连接的持续推送数据
  • 错误使用FutureBuilder适配长连接场景:FutureBuilder仅响应单次Future完成事件,无法感知后续推送的新数据
  • 每次调用方法都新建HubConnection实例,未做连接生命周期管理,容易出现连接泄漏、重复连接问题

非JSON格式数据接收说明

SignalR客户端完全支持接收非JSON格式的普通对象,包括纯文本、二进制流等类型,只要和服务端约定好通信协议,不需要强制将数据转换为JSON结构即可正常解析渲染。

正确实现代码

1. 定义状态字段

late HubConnection _hubConnection;
// 存储接收到的GPS数据
String? _gpsData;
// 存储连接状态,用于处理加载、错误场景
String _connectionStatus = "connecting";

2. 初始化连接与消息监听

@override
void initState() {
  super.initState();
  _initSignalRConnection();
}

Future<void> _initSignalRConnection() async {
  try {
    _hubConnection = HubConnectionBuilder()
        .withUrl('http://secure/secure')
        .build();

    // 注册服务端推送消息监听,方法名需和服务端配置的推送方法名完全一致
    _hubConnection.on('PushGPSData', (arguments) {
      if (arguments?.isNotEmpty ?? false) {
        // arguments[0]即为服务端推送的原始数据,非JSON格式可直接转对应类型处理
        setState(() {
          _gpsData = arguments![0].toString();
        });
      }
    });

    // 监听连接关闭事件
    _hubConnection.onclose(({error}) {
      if (!mounted) return;
      setState(() {
        _connectionStatus = error == null ? "connection_closed" : "connect_error: ${error.toString()}";
      });
    });

    // 启动连接
    await _hubConnection.start();

    if (_hubConnection.state == HubConnectionState.Connected) {
      // 连接成功后可主动拉取一次初始数据
      final initialGpsValue = await _hubConnection.invoke('GetGPSDateTime');
      if (!mounted) return;
      setState(() {
        _connectionStatus = "connected";
        _gpsData = initialGpsValue?.toString();
      });
    }
  } catch (e) {
    if (!mounted) return;
    setState(() {
      _connectionStatus = "connect_error: ${e.toString()}";
    });
  }
}

// 页面销毁时关闭连接,避免内存泄漏
@override
void dispose() {
  _hubConnection.stop();
  super.dispose();
}

3. 构建UI

@override
Widget build(BuildContext context) {
  return Scaffold(
    appBar: AppBar(),
    body: Center(
      child: _connectionStatus != "connected"
          ? Text(_connectionStatus)
          : Text(
              _gpsData ?? "Waiting for GPS data...",
              style: const TextStyle(fontSize: 16),
            ),
    ),
  );
}

注意事项

  • 如果接收的是二进制类型普通对象,直接将arguments[0]转换为Uint8List类型做后续解析即可,无需经过JSON序列化流程
  • 所有触发UI更新的setState调用前必须判断mounted状态,避免组件销毁后执行操作抛出异常
  • 需保证SignalR客户端和服务端的通信协议版本一致,否则可能出现连接成功但无法接收消息的问题

内容的提问来源于stack exchange,提问作者user16357470

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 03:03:26