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
相关产品推荐
相关产品推荐

