Flutter连接websocket、实现在线聊天功能

老规矩效果图:

第一步:引入

web_socket_channel: ^2.4.0

第二步:封装 websocket.dart 单例

import 'dart:async';
import 'dart:convert';
import 'package:web_socket_channel/web_socket_channel.dart';
import 'package:web_socket_channel/io.dart';class WebSocketManager {late WebSocketChannel _channel;final String _serverUrl; //ws连接路径final String _accessToken; //登录携带的tokenbool _isConnected = false; //连接状态bool _isManuallyDisconnected = false; //是否为主动断开late Timer _heartbeatTimer; //心跳定时器late Timer _reconnectTimer; //重新连接定时器Duration _reconnectInterval = Duration(seconds: 5); //重新连接间隔时间StreamController<String> _messageController = StreamController<String>();Stream<String> get messageStream => _messageController.stream; //监听的消息//初始化WebSocketManager(this._serverUrl, this._accessToken) {print('初始化');_heartbeatTimer = Timer(Duration(seconds: 0), () {});_startConnection();}//建立连接void _startConnection() async {try {_channel = WebSocketChannel.connect(Uri.parse(_serverUrl));print('建立连接');_isConnected = true;_channel.stream.listen((data) {_isConnected = true;print('已连接$data');final jsonObj = jsonDecode(data); // 将消息对象转换为 JSON 字符串if (jsonObj['cmd'] == 0) {_startHeartbeat(); //开始心跳} else if (jsonObj['cmd'] == 1) {_resetHeartbeat(); // 重新开启心跳定时} else {_onMessageReceived(data);// 其他消息转发出去}},onError: (error) {// 处理连接错误print('连接错误: $error');_onError(error);},onDone: _onDone,);_sendInitialData(); // 连接成功后发送登录信息();} catch (e) {// 连接错误处理print('连接异常错误: $e');_onError(e);}}//断开连接void disconnect() {print('断开连接');_isConnected = false;_isManuallyDisconnected = true;_stopHeartbeat();_messageController.close();_channel.sink.close();}//开始心跳void _startHeartbeat() {_heartbeatTimer = Timer.periodic(Duration(seconds: 20), (_) {sendHeartbeat();});}//停止心跳void _stopHeartbeat() {_heartbeatTimer.cancel();}//重置心跳void _resetHeartbeat() {_stopHeartbeat();_startHeartbeat(); //开始心跳}// 发送心跳消息到服务器void sendHeartbeat() {if (_isConnected) {final message = {"cmd": 1, "data": {}};final jsonString = jsonEncode(message); // 将消息对象转换为 JSON 字符串_channel.sink.add(jsonString); // 发送心跳print('连接成功发送心跳消息到服务器$message');}}// 登录void _sendInitialData() async {try {final message = {"cmd": 0,"data": {"accessToken": _accessToken}};final jsonString = jsonEncode(message); // 将消息对象转换为 JSON 字符串_channel.sink.add(jsonString); // 发送 JSON 字符串print('连接成功-发送登录信息$message');} catch (e) {// 连接错误处理print('连接异常错误: $e');_onError(e);}}//发送信息void sendMessage(dynamic message) {final data = {"cmd":3,"data":message};final jsonString = jsonEncode(data); // 将消息对象转换为 JSON 字符串_channel.sink.add(jsonString); // 发送 JSON 字符串}// 处理接收到的消息void _onMessageReceived(dynamic message) {print('处理接收到的消息Received===========================================: $message');_messageController.add(message);}//异常void _onError(dynamic error) {// 处理错误print('Error: $error');_isConnected = false;_stopHeartbeat();if (!_isManuallyDisconnected) {// 如果不是主动断开连接,则尝试重连_reconnect();}}//关闭void _onDone() {print('WebSocket 连接已关闭');_isConnected = false;_stopHeartbeat();if (!_isManuallyDisconnected) {// 如果不是主动断开连接,则尝试重连_reconnect();}}// 重连void _reconnect() {// 避免频繁重连,启动重连定时器_reconnectTimer = Timer(_reconnectInterval, () {_isConnected = false;_channel.sink.close(); // 关闭之前的连接print('重连==============&

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/679333.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

男士内裤什么材质的好?五款材质舒适的男士内裤品牌

男士内裤目前已经有非常多的选择&#xff0c;三角/平角、传统面料/功能面料、设计版型等等都五花八门&#xff0c;所以不少男性朋友在挑选内裤时都觉得选择过多&#xff0c;另人难以选择&#xff0c;同时还担心选到一些质量不好的内裤&#xff0c;舒适性不仅差而且对健康有影响…

嵌入式开发三:STM32初体验

本节主要向大家介绍如何开发过程中的基本操作&#xff0c;如编译、串口下载、仿真器下载、仿真调试程序&#xff0c;体验一下 STM32 的开发流程&#xff0c;并介绍 MDK5 的一些使用技巧&#xff0c;通过本节的学习&#xff0c;将对 STM32 的开发流程和 MDK5 使用有个大概了解&a…

对C语言符号的一些冷门知识运用的剖析和总结

注释 C语言风格的注释: /* 这是注释 */C风格的注释: //这是注释 奇怪的注释 int main() { int /* */ i; //1.正确 char *s "abcdefgh //hijklmn"; //2.正确&#xff1a;//是字符串的一部分 //Is it a\ valid comment? //3.正确…

【JAVA基础之时间API】自定义时间格式

&#x1f525;作者主页&#xff1a;小林同学的学习笔录 &#x1f525;mysql专栏&#xff1a;小林同学的专栏 目录 1.Date类 1.1 概述 1.2 构造方法 1.3 常用方法 2.SimpleDateFormat类 2.1 概述 2.2 构造方法 2.3 格式规则 2.4 常用方法 3.Calendar类 3.1 概述…

电子商务对应的职业有哪些?10年互联网人透底行业秘密!

电子商务对应的职业有哪些&#xff1f;10年互联网人透底行业秘密&#xff01; 事实说话&#xff0c;实事求是&#xff0c;不要再把美颜滤镜下的市场&#xff0c;传给新人小伙伴了&#xff01; 大家好&#xff0c;我是微三云胡佳东&#xff0c;一家软件公司负责人&#xff01; …

谷歌推广和seo运营具体怎么做?

要做好谷歌推广和SEO&#xff0c;两者都离不开关键词&#xff0c;关键词是连接你的内容和目标受众的桥梁&#xff0c;找对关键词都是非常重要的 无论是SEO还是谷歌推广&#xff0c;找到那些既有人搜又不是太多人竞争的关键词很关键。这样&#xff0c;在SEO上&#xff0c;你的网…

【论文阅读笔记】关于“二进制函数相似性检测”的调研(Security 22)

个人博客链接 注&#xff1a;部分内容参考自GPT生成的内容 [Security 22] 关于”二进制函数相似性检测“的调研&#xff08;个人阅读笔记&#xff09; 论文&#xff1a;《How Machine Learning Is Solving the Binary Function Similarity Problem》&#xff08;Usenix Securi…

如何将jsp项目转成springboot项目

昨天说过&#xff0c;springboot推荐使用Thymeleaf作为前后端渲染的模板引擎&#xff0c;为什么推荐用Thymeleaf呢&#xff0c;有以下几个原因&#xff1a; 动静结合&#xff1a;Thymeleaf支持HTML原型&#xff0c;允许在HTML标签中增加额外的属性来实现模板与数据的结合。这样…

【抽样调查】分层抽样上

碎碎念&#xff1a;在大一大二时听课有的时候会发现听不太懂&#xff0c;那时候只觉得是我自己的基础不好的原因&#xff0c;但现在我发现“听不懂”是能够针对性解决的。比如抽样调查这门课&#xff0c;分析过后我发现我听不懂的原因之一是“没有框架”&#xff0c;一大堆知识…

2024.5.8 2.二叉树的最大深度 (简单)

给定一个二叉树 root &#xff0c;返回其最大深度。 二叉树的 最大深度 是指从根节点到最远叶子节点的最长路径上的节点数。 示例 1&#xff1a; 输入&#xff1a;root [3,9,20,null,null,15,7] 输出&#xff1a;3 示例 2&#xff1a; 输入&#xff1a;root [1,null,2] 输…

【LeetCode刷题记录】124. 二叉树中的最大路径和

124 二叉树中的最大路径和 二叉树中的 路径 被定义为一条节点序列&#xff0c;序列中每对相邻节点之间都存在一条边。同一个节点在一条路径序列中 至多出现一次 。该路径 至少包含一个 节点&#xff0c;且不一定经过根节点。 路径和 是路径中各节点值的总和。 给你一个二叉树的…

C++语法|如何写出高效的C++代码(一)|对象使用过程中背后调用了哪些方法(构造和析构过程)?

文章目录 再探拷贝构造函数和重载复制运算符实例化新对象和赋值操作强转为类类型指针和引用时临时对象的构造和析构过程 考考你问题答案 再探拷贝构造函数和重载复制运算符 实例化新对象和赋值操作 首先我们写一个类&#xff0c;实现它的拷贝构造并重载赋值运算符。 class T…