Harmony OS 简易聊天应用开发全解析
一、引言
在 Harmony OS NEXT / 5.0 / API 12 + 版本的生态下,开发一款简易聊天应用是探索鸿蒙应用开发的有趣实践。本文将详细介绍该聊天应用的功能实现、源码解析以及问题优化策略,帮助开发者快速上手并深入理解相关技术要点。
二、适用版本
本文所涉及的简易聊天功能适用于 Harmony OS NEXT / 5.0 / API 12 + 版本。这些版本为开发者提供了丰富且稳定的 API,使我们能够轻松实现并优化聊天应用所需的网络通信、界面展示等关键功能。
三、效果预览

四、基础代码结构剖析
- 核心组件 ChatApp:作为整个聊天应用的 “中枢神经”,ChatApp 组件统筹管理着聊天过程中的各类状态与逻辑。
- 状态变量:
- messages 数组:犹如一个 “聊天记录宝库”,它将所有的聊天消息妥善存储,为用户提供随时回顾聊天内容的可能。
- inputText:恰似输入框的 “贴身记录员”,实时跟踪并记录用户在输入框中输入的每一个字符。
- isConnected:可看作一个 “连接状态信号灯”,以布尔值的形式直观反映当前应用与服务器的连接状态。
- ws:作为 WebSocket 对象,它是应用与服务器之间进行数据交互的 “高速通道”,初始值为 null,等待被激活以建立通信。
- 方法:
- connect 方法:此方法如同一位 “通信搭建师”,负责创建 WebSocket 实例并尝试连接到指定的服务器
wss://toolin.cn/echo。同时,它还为这条 “通道” 配备了四位 “守护使者”,即 open、message、close、error 事件的监听。当连接成功时,就像通道搭建完成,“信号灯” 变绿(设置isConnected为 true);接收到消息时,迅速将消息 “存入宝库”,添加到messages数组;连接关闭时,“信号灯” 变红(设置isConnected为 false);若发生错误,便在控制台这个 “公告板” 上打印错误信息。 - sendMessage 方法:当输入框中有内容且 “高速通道” 已建立(已连接)时,该方法化身为 “消息快递员”,通过
ws这个 “通道” 将消息发送出去,然后把消息添加到messages数组这个 “宝库” 中,并及时清空输入框,准备迎接下一条消息的到来。
- connect 方法:此方法如同一位 “通信搭建师”,负责创建 WebSocket 实例并尝试连接到指定的服务器
- 状态变量:
五、核心功能详解
- 连接状态管理:
- 状态显示:利用
Text组件作为 “状态播报员”,在线时大声宣告 “🟢 在线”,并且文字颜色呈现为绿色,醒目地向用户传达当前在线状态;离线时则播报 “🔴 离线”,文字变为红色,提醒用户连接已中断。 - 按钮交互:
Button组件宛如一个 “智能切换开关”,依据当前连接状态显示不同的文字。若当前在线,它显示 “断开连接”,用户点击即如同按下 “关闭按钮”,执行断开连接操作;若当前离线,它显示 “点击连接”,用户点击则像按下 “开启按钮”,尝试建立连接。
- 状态显示:利用
- 消息收发演示:
- 输入框:
TextInput组件仿佛一位 “忠实的书记员”,实时捕捉用户输入的内容,并及时同步更新inputText这个 “记录员” 的信息,确保输入内容无一遗漏。 - 发送按钮:另一个
Button组件扮演着 “快递发送员” 的角色,当用户点击它时,迅速调用sendMessage方法,将输入框中的 “包裹”(消息)通过 “高速通道” 发送出去。 - 消息展示:
List组件就像一个精心布置的 “展示画廊”,它遍历messages这个 “聊天记录宝库”,以气泡样式将每条消息精美地展示出来。并且,根据消息是发送方还是接收方,为气泡披上不同颜色的 “外衣”,发送方气泡背景色为 #e3f2fd,接收方气泡背景色为 #ffffff,让用户能够轻松区分不同来源的消息。
- 输入框:
- 自动重连机制(心跳机制):
- reconnect 方法:此方法犹如一位 “执着的网络修复工”,借助
setTimeout这个 “定时器”,在连接断开 3 秒后,准时尝试重新搭建 “高速通道”,努力恢复应用与服务器的连接。 - 自动重连实现:在
ws的close事件监听中,不仅将isConnected这个 “信号灯” 熄灭(设置为 false),还立即调用reconnect方法,让 “网络修复工” 马上投入工作,实现自动重连,确保应用在连接断开时能尽快恢复通信。
- reconnect 方法:此方法犹如一位 “执着的网络修复工”,借助
六、源码详情解读
// 从 @ohos.net.webSocket 导入 webSocket 模块,用于 WebSocket 通信
import webSocket from '@ohos.net.webSocket';
// 从 @kit.ArkUI 导入 promptAction,用于显示弹窗
import { promptAction } from '@kit.ArkUI';
// 定义 Message 类,表示一条聊天消息
class Message {
// 消息类型,sent 表示发送,received 表示接收
type: string;
// 消息内容
content: string;
// 时间戳
timestamp: number;
constructor(type: string, content: string) {
this.type = type;
this.content = content;
this.timestamp = new Date().getTime();
}
}
// 定义 WebSocketDemo 组件
@Component
export struct WebSocketDemo {
// 连接状态
@State isConnected: boolean = false;
// 输入框内容
@State inputMessage: string = '';
// 聊天记录数组
@State messages: Message[] = [];
// WebSocket 对象
private ws: webSocket.WebSocket | null = null;
// 初始化 WebSocket 连接
initWebSocket() {
const socketUrl = 'wss://toolin.cn/echo';
this.ws = webSocket.create(socketUrl);
if (this.ws) {
// 连接成功事件
this.ws.on('open', () => {
this.isConnected = true;
});
// 接收消息事件
this.ws.on('message', (data) => {
const message = new Message('received', data);
this.addMessage(message);
});
// 连接关闭事件
this.ws.on('close', () => {
this.isConnected = false;
this.reconnect();
});
// 错误事件
this.ws.on('error', (error) => {
console.error('WebSocket error:', error);
this.showAlert('连接错误', 'WebSocket 连接出现错误,请检查网络');
});
// 发起连接
this.ws.connect();
}
}
// 添加消息到聊天记录
addMessage(message: Message) {
this.messages.push(message);
}
// 显示弹窗
showAlert(title: string, content: string) {
promptAction.showToast({
message: content,
duration: 3000
});
}
// 重新连接
reconnect() {
setTimeout(() => {
this.initWebSocket();
}, 3000);
}
// 发送消息
sendMessage() {
if (this.isConnected && this.inputMessage.trim()!== '') {
const message = new Message('sent', this.inputMessage);
this.addMessage(message);
if (this.ws) {
this.ws.send(this.inputMessage);
}
this.inputMessage = '';
}
}
// 构建组件界面
build() {
Column() {
// 显示连接状态
Text(this.isConnected? '🟢 在线' : '🔴 离线')
.fontSize(16)
.fontWeight(500)
.fontColor(this.isConnected? '#00ff00' : '#ff0000');
Row() {
// 连接/断开连接按钮
Button(this.isConnected? '断开连接' : '点击连接')
.width(120)
.height(40)
.onClick(() => {
if (this.isConnected) {
if (this.ws) {
this.ws.close();
}
} else {
this.initWebSocket();
}
});
// 清空记录按钮
Button('清空记录')
.width(120)
.height(40)
.onClick(() => {
this.messages = [];
});
}
.padding({ top: 20 });
Row() {
// 消息输入框
TextInput({ placeholder: '请输入消息', text: $this.inputMessage })
.width(250)
.height(40)
.padding({ left: 10, right: 10 });
// 发送按钮
Button('发送')
.width(80)
.height(40)
.onClick(() => {
this.sendMessage();
});
}
.padding({ top: 20 });
// 消息列表
List(this.messages) {
Item({ index: 0 }) {
Row() {
if (this.item.type ==='sent') {
Column() {
Text(this.item.content)
.backgroundColor('#e3f2fd')
.padding(10)
.cornerRadius(10);
Text(new Date(this.item.timestamp).toLocaleTimeString())
.fontSize(12)
.alignSelf(TextAlign.End);
}
.layoutWeight(1);
} else {
Column() {
Text(this.item.content)
.backgroundColor('#ffffff')
.padding(10)
.cornerRadius(10);
Text(new Date(this.item.timestamp).toLocaleTimeString())
.fontSize(12)
.alignSelf(TextAlign.Start);
}
.layoutWeight(1);
}
}
}
}
.width('100%')
.layoutWeight(1);
}
.width('100%')
.height('100%')
.padding(20);
}
}
上述源码完整地呈现了鸿蒙简易聊天应用的实现。从导入必要的模块,到定义消息类和组件,再到各个功能方法的实现以及界面的构建,每一部分都紧密协作。WebSocketDemo 组件通过管理各种状态变量和方法,实现了连接状态管理、消息收发以及自动重连等核心功能。在界面构建部分,通过合理运用 Column、Row、Text、Button、TextInput 和 List 等组件,打造出一个简洁且功能完备的聊天界面。
七、问题优化策略
1、权限配置问题:
- 存在原因:网络请求在鸿蒙系统中需要相应的权限支持,如同车辆行驶需要道路许可。当应用缺少网络权限时,网络请求就会失败,并在控制台报错
PERMISSION_DENIED。 - 解决方法:在
module.json5配置文件中添加网络权限配置,为网络请求授予许可。配置如下
"requestPermissions": [
{
"name": "ohos.permission.INTERNET",
}
]
2、消息安全性风险:
- 过滤方法:通过
sanitizeMessage方法对消息内容进行过滤,以防范潜在的安全风险。该方法类似于一个 “消息安检员”,将消息中的<和>替换为实体字符,有效防止跨站脚本攻击(XSS)。同时,限制消息长度为 500 字符,避免过长消息可能引发的性能问题或其他异常。
// 消息内容过滤
private sanitizeMessage(content: string): string {
return content
.replace(/</g, '<')
.replace(/>/g, '>')
.substring(0, 500); // 限制消息长度
}
在发送消息前,调用此方法对消息内容进行处理,确保消息的安全性。例如,在 sendMessage 方法中修改为:
sendMessage() {
if (this.isConnected && this.inputMessage.trim()!== '') {
const sanitizedMessage = this.sanitizeMessage(this.inputMessage);
const message = new Message('sent', sanitizedMessage);
this.addMessage(message);
if (this.ws) {
this.ws.send(sanitizedMessage);
}
this.inputMessage = '';
}
}
3、防止频繁发送:
- 控制逻辑:定义
lastSendTime记录上次发送消息的时间,以此作为频率控制的依据。在sendMessage方法中,每次发送消息时检查当前时间与lastSendTime的间隔。若间隔小于 1000 毫秒(1 秒),则提示用户 “发送太频繁啦!” 并阻止发送;否则,执行正常发送逻辑,并更新lastSendTime。
private lastSendTime: number = 0;
sendMessage() {
if (Date.now() - this.lastSendTime < 1000) {
promptAction.showToast({ message: '发送太频繁啦!' });
return;
}
if (this.isConnected && this.inputMessage.trim()!== '') {
const sanitizedMessage = this.sanitizeMessage(this.inputMessage);
const message = new Message('sent', sanitizedMessage);
this.addMessage(message);
if (this.ws) {
this.ws.send(sanitizedMessage);
}
this.inputMessage = '';
this.lastSendTime = Date.now();
}
}
八、总结
通过这个简化版的鸿蒙聊天应用,开发者能够深入了解在 Harmony OS NEXT / 5.0 / API 12 + 版本下开发聊天应用的关键技术和流程。在实际开发中,可以此为基础,逐步拓展功能,如增加用户认证提升安全性、实现群聊功能丰富交互场景、支持多媒体消息增强用户体验等。同时,务必重视应用的安全性和稳定性,合理处理权限配置、消息安全等问题,为用户打造可靠、优质的应用。关于鸿蒙应用开发中聊天功能的更多进阶技巧和优化思路,我会在后续博客中持续分享,感兴趣的话欢迎关注。对于这个聊天应用的实现和优化,你若有任何疑问或想法,欢迎随时交流。
更多推荐

所有评论(0)