欢迎加入开源鸿蒙跨平台社区:
https://openharmonycrossplatform.csdn.net

Flutter WebSocket 在 OpenHarmony 即时通讯场景中的实践与踩坑记录

前言

最近在做 Flutter for OpenHarmony 项目时,接了一个即时通讯模块。

功能其实不复杂:

  • 实时聊天
  • 在线状态同步
  • 消息推送
  • 心跳保活

一开始我以为直接用 Flutter WebSocket 就能搞定。

结果真正跑到 OpenHarmony 真机上之后,还是遇到了不少问题。

包括:

  • WebSocket 偶发断连
  • 切后台后连接丢失
  • 弱网环境重连失败
  • 页面退出后连接没释放
  • 多次进入页面重复创建连接

这些问题在 Android 上偶尔也有,但在鸿蒙设备上会更容易暴露。

后面花了不少时间重新整理 WebSocket 管理逻辑,稳定性才慢慢好起来。

这篇文章主要记录一下我这次在 OpenHarmony 项目里的 WebSocket 实践过程。


一、项目里的实际场景

当前项目主要有几个实时功能:

功能 说明
聊天消息 实时接收
在线状态 用户上线提醒
系统通知 后台推送
消息未读数 实时更新

HTTP 轮询肯定不太适合。

所以最后还是用了 WebSocket 长连接。


二、Flutter WebSocket 基础接入

我这里直接使用:


web_socket_channel

添加依赖


dependencies:
  web_socket_channel: ^2.4.0

执行:


flutter pub get

三、基础连接代码

最开始我的代码其实很简单。


final channel = WebSocketChannel.connect(
  Uri.parse("wss://test.com/ws"),
);

发送消息:


channel.sink.add("hello");

监听消息:


channel.stream.listen((event) {

  print(event);
});

关闭连接:


channel.sink.close();

Demo 阶段没问题。

但真正进入业务后:

问题开始慢慢变多。


四、最先遇到的问题:重复连接

这个问题我一开始没注意。


问题现象

聊天页面:

每次进入:

都会重新创建 WebSocket。


initState() {
  connectSocket();
}

结果:

多进出几次页面后:

服务端直接出现多个连接。

客户端也开始:

  • 重复收到消息
  • 消息顺序异常
  • 内存占用升高

后来的解决方式

我后面把 WebSocket 单独抽成了全局管理类。


class SocketManager {

  static final SocketManager _instance =
      SocketManager._internal();

  factory SocketManager() {
    return _instance;
  }

  SocketManager._internal();
}

整个项目只维护一个连接。

问题稳定很多。


五、心跳机制一定要做

这个问题在 OpenHarmony 上特别明显。


问题

长时间不操作:

连接会被服务端断开。

但客户端:

有时候并不知道已经断了。

结果:

用户看起来在线。

实际已经收不到消息。


后来的方案

增加心跳。


Timer.periodic(
  const Duration(seconds: 30),
  (_) {

    sendPing();
  },
);

发送:


channel.sink.add(
  jsonEncode({
    "type": "ping"
  }),
);

服务端返回 pong。

这样连接稳定很多。


六、断线重连是必须的

这个是实际项目里最重要的一部分。


我遇到的场景

比如:

  • 用户切 WiFi
  • 网络波动
  • App 切后台
  • 鸿蒙系统回收连接

WebSocket 都可能断掉。


后来的重连方案

监听:


onDone

和:


onError

channel.stream.listen(

  onDone: () {
    reconnect();
  },

  onError: (e) {
    reconnect();
  },
);

重连逻辑


void reconnect() async {

  await Future.delayed(
    const Duration(seconds: 3),
  );

  connect();
}

这个方案目前在 OpenHarmony 上稳定性还不错。


七、切后台导致连接断开的问题

这个是我在鸿蒙真机上最容易复现的问题。


问题现象

App 切后台几分钟后:

WebSocket 自动断开。

回到前台:

连接不会自动恢复。


后来的处理方式

监听页面生命周期。


class AppStateListener
    with WidgetsBindingObserver {
}

监听:


didChangeAppLifecycleState

@override
void didChangeAppLifecycleState(
    AppLifecycleState state) {

  if (state ==
      AppLifecycleState.resumed) {

    reconnect();
  }
}

这个优化之后:

后台恢复稳定很多。


八、消息流不要直接操作 UI

这个问题我刚开始踩得挺明显。


错误做法

收到消息:

直接:


setState(() {
  msgList.add(data);
});

如果消息频率高:

页面会疯狂 rebuild。

在鸿蒙设备上:

聊天列表明显掉帧。


后来的优化

我改成:

  • Provider
  • StreamController
  • ValueNotifier

统一管理消息流。

例如:


messageNotifier.value = newList;

局部刷新。

效果会稳定很多。


九、页面退出一定要释放监听

这个问题很多人容易忘。


问题

页面退出后:

stream.listen 还在。

结果:

  • 重复监听
  • 内存泄漏
  • 多次收到消息

正确处理


late StreamSubscription subscription;

页面销毁:


@override
void dispose() {

  subscription.cancel();

  super.dispose();
}

这个在 OpenHarmony 长时间运行时挺关键。


十、弱网环境测试

这个我建议一定要做。


我测试的场景

  • WiFi 切换
  • 飞行模式
  • 弱网
  • 后台恢复

重点观察:

  • 是否自动重连
  • 消息是否丢失
  • UI 是否卡顿

实际结果

优化前:

问题 表现
断线 高频
重连失败 偶发
消息重复 存在
页面卡顿 明显

优化后:

项目 效果
长连接稳定性 提升明显
后台恢复 基本正常
消息同步 稳定
页面流畅度 更好

目前项目里已经稳定运行了一段时间。


十一、我最终的 WebSocket 管理结构

后面我把整个连接逻辑统一封装成:


SocketManager

内部包括:

  • connect
  • reconnect
  • send
  • heartBeat
  • close

业务层:

只负责收消息。

这样后面维护轻松很多。


十二、总结

这次做 Flutter WebSocket 在 OpenHarmony 下的适配,一个比较明显的感受是:

即时通讯真正难的其实不是“连上”。

而是:

  • 断线处理
  • 生命周期管理
  • 弱网恢复
  • 消息同步
  • 长时间稳定性

尤其 OpenHarmony 真机环境下:

后台切换和网络变化会比模拟器更容易暴露问题。

我现在项目里的原则基本是:

  • WebSocket 全局单例
  • 必做心跳
  • 必做重连
  • 页面退出释放监听
  • 生命周期统一管理

整体稳定性会好很多。

后面我还准备继续研究:

  • MQTT 在 OpenHarmony 下的表现
  • Flutter IM 架构优化
  • WebSocket 消息队列
  • 离线消息同步方案

希望这篇文章能给正在做 Flutter for OpenHarmony 开发的同学一点参考。

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐