基于 ArkTS 与 HarmonyOS 6.0 的 AI 智能助手应用开发实践
基于 ArkTS 与 HarmonyOS 6.0 的 AI 智能助手应用开发实践



一、引言
随着 HarmonyOS 6.0 的发布,ArkTS 语言在类型安全、状态管理、并发模型等方面迎来了重大升级。本文通过一个完整的 AI 智能助手应用案例,深入剖析 HarmonyOS 6.0 核心特性的实际运用,涵盖声明式 UI、状态管理装饰器、流式数据渲染、偏好设置持久化、自定义弹窗组件等关键技术点。
该应用实现了三大核心功能模块:AI 智能对话(支持流式逐字输出)、多语言翻译与文本总结、个性化设置(主题切换、字体大小、功能开关)。项目采用分层架构设计,严格遵循 ArkTS 严格模式规范,无任何编译错误或警告,可作为 HarmonyOS 6.0 应用开发的教学参考。
二、项目架构设计
2.1 目录结构
entry/src/main/ets/
├── models/
│ └── ChatModel.ets # 数据模型层
├── services/
│ └── AiService.ets # AI 业务服务层
├── common/
│ └── Constants.ets # 全局常量与配置
├── components/
│ ├── ChatBubble.ets # 聊天气泡组件
│ ├── ChatInput.ets # 消息输入组件
│ └── LoadingIndicator.ets # 加载动画组件
├── pages/
│ ├── Index.ets # 主入口页(Tabs 导航)
│ ├── ChatPage.ets # AI 对话页
│ ├── TranslatePage.ets # 翻译/总结页
│ └── SettingsPage.ets # 设置页
├── entryability/
│ └── EntryAbility.ets # 应用入口
└── entrybackupability/
└── EntryBackupAbility.ets # 备份恢复
2.2 分层架构
项目采用经典的 MVVM 三层架构:
- Model 层(models/ChatModel.ets):定义消息实体、会话实体、消息角色枚举、消息类型枚举等核心数据结构。使用
@Observed装饰器使类属性变化可被监听,为后续@ObjectLink绑定提供基础。 - Service 层(services/AiService.ets):封装所有 AI 业务逻辑,包括消息发送、流式响应生成、文本翻译、文本总结、代码解释等方法。采用静态方法设计,无状态、纯函数式的服务类。
- View 层(components + pages):组件层负责可复用的 UI 单元(聊天气泡、输入框、加载动画),页面层负责页面布局与状态管理。页面通过
@Component装饰器声明,组件间通过@Prop、@Provide/@Consume等装饰器进行数据传递。
2.3 路由设计
应用采用单页面架构,仅注册一个入口路由 pages/Index。内部通过 Tabs 组件实现三 Tab 底部导航切换,ChatPage、TranslatePage、SettingsPage 作为子组件在 Index.ets 中通过 import 引入使用,无需独立路由注册。这种设计减少了页面跳转的开销,保证了 Tab 切换时的状态保持。
三、HarmonyOS 6.0 核心特性深度运用
3.1 状态管理装饰器体系
HarmonyOS 6.0 的状态管理装饰器是构建响应式 UI 的核心。本应用全面覆盖了六大装饰器:
@State —— 组件内状态
每个页面组件通过 @State 声明自身状态变量,当变量值变化时自动触发 UI 重渲染。例如 ChatPage 中的消息列表、加载状态、滚动按钮显隐等:
@State messages: ChatMessage[] = []
@State isLoading: boolean = false
@State showScrollToBottom: boolean = false
@Prop —— 父子组件单向传值
子组件通过 @Prop 接收父组件传递的数据,实现单向数据流。例如 ChatBubble 接收消息数据和主题状态:
@Prop message: ChatMessage
@Prop isDarkMode: boolean = false
值得注意的是,ChatBubble 通过 @ObjectLink 监听 @Observed 类的属性变化,当消息的 isStreaming 或 content 属性更新时,气泡自动刷新显示。
@Provide / @Consume —— 跨层级数据共享
isDarkMode 主题状态在 Index.ets 中通过 @Provide 声明,ChatPage、TranslatePage、SettingsPage 三个子组件通过 @Consume 获取,无需逐层传递 props:
// Index.ets —— 提供者
@Provide isDarkMode: boolean = false
// 任意子组件 —— 消费者
@Consume isDarkMode: boolean
这种设计使得主题切换能够即时同步到所有页面,无需手动回调或事件总线。
@Observed / @ObjectLink —— 类属性变化监听
ChatMessage 类使用 @Observed 装饰器修饰,使其内部的 content、isStreaming 等属性变化可被追踪。ChatBubble 通过 @ObjectLink 绑定消息对象,实现流式内容逐字更新时的局部刷新,而非整个消息列表的重渲染。
这是 HarmonyOS 6.0 中性能优化的重要手段——精确到属性级别的响应式更新。
@Builder —— 局部构建器
应用大量使用 @Builder 装饰器将 UI 构建逻辑拆分为可复用的构建函数,如 TitleBar()、TabBarBuilder()、SettingItem()、ClearConfirmSheet()、DarkModeSheet() 等。每个 Builder 函数封装独立的 UI 片段,提高代码可读性和复用性。
3.2 UIContext 动画系统
HarmonyOS 6.0 废弃了全局的 animateTo() 函数,要求通过 UIContext 实例调用动画。本应用在动画场景中统一使用 this.getUIContext()?.animateTo() 模式:
// ChatPage.ets —— 清空对话时的过渡动画
clearConversation(): void {
const uiContext = this.getUIContext()
if (uiContext) {
uiContext.animateTo({
duration: AppConstants.ANIM_DURATION_NORMAL,
curve: Curve.EaseOut
}, () => {
this.addWelcomeMessage()
this.conversationTitle = '新对话'
})
}
}
LoadingIndicator 的打字动画同样采用此模式,配合 setInterval 实现三个圆点的呼吸式闪烁效果。每个圆点通过 @State 控制透明度,在 animateTo 的渐变曲线下产生平滑过渡。
3.3 流式数据渲染
流式输出是 AI 对话应用的核心体验。由于 ArkTS 严格模式不支持生成器函数(async *),本应用采用回调式流式输出方案:
// AiService.ets —— 逐字回调
static async sendMessageStream(
userInput: string,
onChar: (char: string) => void
): Promise<string> {
const fullResponse = await AiService.getResponse(userInput)
const chars = fullResponse.split('')
for (let i = 0; i < chars.length; i++) {
await AiService.delay(30 + Math.random() * 40)
onChar(chars[i])
}
return fullResponse
}
// ChatPage.ets —— 回调中更新 UI
let fullContent = ''
await AiService.sendMessageStream(text, (char: string) => {
fullContent += char
const updatedMessages = [...this.messages]
updatedMessages[updatedMessages.length - 1].content = fullContent
this.messages = updatedMessages
this.scrollToEnd()
})
每次回调触发时,通过扩展运算符创建新数组引用,确保 @State 能检测到变化并触发 UI 更新。同时调用 scrollToEnd() 保持消息列表自动滚动到底部。
3.4 Preferences 持久化存储
应用通过 @kit.ArkData 的 preferences API 实现设置的持久化存储。在 HarmonyOS 6.0 中,getContext(this) 已被废弃,改为通过 this.getUIContext().getHostContext() 获取上下文:
async loadSettings(): Promise<void> {
const hostContext = this.getUIContext().getHostContext() as common.Context
this.dataPreferences = await preferences.getPreferences(
hostContext,
AppConstants.STORE_KEY_SETTINGS
)
this.fontSize = await this.dataPreferences.get('fontSize', 16) as number
this.darkMode = await this.dataPreferences.get('darkMode', 'auto') as string
}
支持持久化的设置项包括:深色模式(auto/light/dark)、字体大小(14px/16px/18px)、流式响应开关、语音输入开关。每次修改后通过 flush() 确保数据立即写入磁盘。
3.5 bindSheet 自定义弹窗
HarmonyOS 6.0 中 AlertDialog.show 的 API 参数类型发生变化,本应用全面改用 bindSheet 底部弹窗。相比 AlertDialog,bindSheet 的优势在于:
- 完全自定义 UI:支持任意组件布局,而非固定模板
- 拖拽交互:通过
dragBar: true支持用户拖拽关闭 - 声明式绑定:通过
$$双向绑定控制显隐 - 动画自然:底部滑入滑出动画更符合移动端交互习惯
应用中的三个弹窗场景均采用 bindSheet 实现:
| 场景 | 弹窗组件 | 用途 |
|---|---|---|
| 清空对话确认 | ClearConfirmSheet |
双按钮确认/取消 |
| 主题模式选择 | DarkModeSheet |
三选项列表:跟随系统/浅色/深色 |
| 字体大小选择 | FontSizeSheet |
三选项列表:小/中/大 |
每个弹窗通过 @State 布尔变量控制显隐,通过 $$ 语法实现双向绑定:
.bindSheet($$this.darkModeDialogShow, this.DarkModeSheet(), {
height: 320,
dragBar: true,
backgroundColor: this.isDarkMode ? AppConstants.COLOR_CARD_DARK : Color.White,
maskColor: '#00000080'
})
3.6 Scroll 与 onDidScroll
HarmonyOS 6.0 中 onScroll 已被 onDidScroll 替代。ChatPage 通过 onDidScroll 监听滚动偏移量,实现"滚动到底部"浮动按钮的显隐控制:
Scroll(this.scroller) {
// 消息列表内容
}
.onDidScroll((_xOffset: number, yOffset: number) => {
this.showScrollToBottom = yOffset < -100
})
当用户向上滚动超过 100vp 时,右下角出现一个圆形按钮,点击后通过 scroller.scrollEdge(Edge.Bottom) 平滑滚动到底部。按钮的显隐使用 transition(TransitionEffect.OPACITY) 实现淡入淡出效果。
3.7 promptAction.openToast
HarmonyOS 6.0 废弃了 promptAction.showToast,改为 promptAction.openToast。为避免异常抛出,所有 Toast 调用均包裹在 try/catch 中:
private showToastMsg(msg: string): void {
try {
promptAction.openToast({ message: msg, duration: 2000 })
} catch (e) {
console.error('Toast error:', JSON.stringify(e))
}
}
四、三大核心功能模块详解
4.1 AI 智能对话模块
对话模块是应用的核心入口,实现了完整的聊天交互体验。
消息生命周期:用户发送消息 → 创建 User 消息 → 创建空 AI 消息(标记 isStreaming = true)→ 流式填充内容 → 标记 isStreaming = false → 更新对话标题。
消息气泡设计:ChatBubble 组件根据消息角色(USER/AI/SYSTEM)展示不同的气泡样式。用户消息右对齐,蓝色背景;AI 消息左对齐,灰色背景;系统消息居中,淡色提示。流式输出中的消息通过 @ObjectLink 绑定,内容逐字更新时气泡自动扩展。
打字指示器:LoadingIndicator 组件在 AI 生成回复前显示三个呼吸圆点动画。通过 setInterval 循环切换圆点透明度,使用 UIContext.animateTo 实现平滑过渡。组件在 aboutToDisappear 生命周期中清理定时器,防止内存泄漏。
对话管理:支持清空全部对话,通过 bindSheet 弹窗二次确认。清空后恢复欢迎消息,对话标题重置为"新对话"。首条用户消息的前 15 个字符自动截取为对话标题。
4.2 多语言翻译与文本总结模块
翻译模块采用双面板布局,支持语言对调功能。
语言选择器:自定义下拉选择器替代原生 Select 组件。点击语言标签后弹出 bindSheet,列表展示六种语言:中文、English、日本語、한국어、Français、Deutsch。选中项带勾选标记,支持流畅滚动。
语言对调:中间的交换按钮一键交换源语言和目标语言,同时交换输入框和输出框的内容,提升双语对照翻译的便捷性。
翻译逻辑:AiService 通过 TranslationEntry 类管理翻译映射。根据源语言和目标语言匹配返回对应的翻译结果。实际项目中可替换为调用大模型 API。
文本总结:独立 Tab 页,专为大段文本的要点提取设计。输出包含原文字符数统计、段落数估算、核心要点列表和内容摘要预览。
Tab 切换动画:翻译和总结两个 Tab 通过自定义指示器实现平滑过渡。指示器使用 offset 和 animation 属性,在 Tab 切换时水平滑动到目标位置。
4.3 个性化设置模块
设置页面采用分组列表布局,分为"外观设置"、“AI 功能”、"关于"三个 Section。
深色模式:支持三种模式——跟随系统、浅色模式、深色模式。选择后通过 @Consume 机制立即同步到所有子页面。设置值通过 Preferences 持久化,下次启动自动恢复。
字体大小:提供 14px / 16px / 18px 三档选择。持久化后可在 ChatPage 和 TranslatePage 中消费使用,调整消息文字和翻译文本的显示大小。
AI 功能开关:流式响应开关控制是否启用逐字输出效果,语音输入开关预留了语音交互能力。关闭流式响应时,AI 回复将一次性展示完整内容。
版本信息:展示应用版本号和技术栈信息,便于开发者调试和用户了解。
五、技术亮点与最佳实践
5.1 严格模式合规
ArkTS 严格模式对类型安全、API 使用、语法规范有严格要求。本应用在开发过程中解决了以下典型问题:
- 索引签名:放弃
interface { [key: string]: string },改用class显式字段定义 - 生成器函数:放弃
async *语法,改用回调式模拟流式输出 - 索引访问:放弃
obj[key]动态属性访问,改用 for 循环遍历 + 条件判断 - 对象字面量:所有匿名对象字面量必须对应显式声明的 class 或 interface
- 弃用 API:全面迁移
getContext(this)→getUIContext().getHostContext()、showToast→openToast、onScroll→onDidScroll、全局animateTo→UIContext.animateTo
5.2 组件化设计
应用遵循"高内聚、低耦合"的组件设计原则:
- ChatBubble:纯展示组件,仅依赖
@Prop和@ObjectLink输入,无副作用 - ChatInput:输入组件,通过回调函数
onSend向父组件传递数据,遵循"子组件通知、父组件处理"的单向数据流 - TypingIndicator:自启动动画组件,在
aboutToAppear中启动定时器,在aboutToDisappear中清理,确保生命周期安全 - SettingItem:通用设置项组件,通过回调参数传递点击事件,可被任意设置页面复用
5.3 性能优化
- 局部更新:流式输出时,通过
@ObjectLink+@Observed实现单条消息的局部刷新,而非整个列表重渲染 - 数组不可变更新:所有状态更新使用扩展运算符创建新数组引用,确保
@State检测到变化 - 定时器清理:所有
setInterval/setTimeout在组件销毁时通过clearInterval清理,防止内存泄漏 - 懒加载:Scroll 组件默认不渲染不可见区域的内容,长消息列表自动优化
5.4 深色模式适配
应用采用系统级的深色模式适配方案。通过 @Provide/@Consume 全局共享 isDarkMode 状态,每个组件内部根据该状态切换颜色值。颜色常量在 AppConstants 中统一定义,包括:
- 背景色(浅色/深色)
- 卡片色(浅色/深色)
- 主文字色(浅色/深色)
- 次要文字色(浅色/深色)
- AI 气泡色(浅色/深色)
- 用户气泡色(浅色/深色)
这种集中式颜色管理使得主题切换逻辑清晰,修改主题色只需更改常量定义。
5.5 错误处理与用户体验
- 网络异常兜底:所有 AI 服务调用包裹在 try/catch 中,失败时显示友好的系统提示消息
- Toast 安全调用:将所有 Toast 调用封装在单独方法中,统一处理可能的异常
- 空状态处理:翻译和总结页面在无输出时显示空白占位区域,而非突兀的空白
- 加载状态反馈:对话模块在等待 AI 回复时显示打字指示器,翻译模块显示"翻译中…"按钮状态
- 二次确认:清空对话等破坏性操作通过 bindSheet 弹窗二次确认,防止误操作
六、关键技术选型说明
6.1 为什么不用 Navigation 路由?
应用采用单页面 Tabs 架构而非多页面路由,原因如下:
- Tab 切换时组件状态保持,切换回对话页时消息列表不会丢失
- 避免路由跳转的动画开销和状态序列化/反序列化
- 三个功能模块是并列关系而非层级关系,符合 Tabs 的交互语义
- 简化了
main_pages.json配置,仅需注册一个入口路由
6.2 为什么用自定义下拉选择器而非 Select?
TranslatePage 中的语言选择器使用自定义 bindSheet 实现,而非系统 Select 组件:
- ArkTS 严格模式下 Select 的
options参数类型要求SelectOption[],与数据模型不匹配 - 自定义实现可以完全控制样式,与整体 UI 风格一致
- bindSheet 的底部滑入动画比 Select 的下拉弹出更符合移动端交互习惯
- 可以灵活添加图标、勾选标记等辅助元素
6.3 为什么用 bindSheet 而非 AlertDialog?
- AlertDialog 的 API 在 HarmonyOS 6.0 中参数格式发生变化,兼容性风险高
- bindSheet 支持完全自定义 UI 布局,不受对话框模板限制
- 底部弹窗的位置更符合手机单手操作热区
- 支持拖拽关闭,交互更自然
6.4 模拟数据 vs 真实 API
当前版本使用内置模拟数据(AI_RESPONSES 数组 + 随机延迟),这是有意为之的设计选择:
- 降低演示门槛:无需配置 API Key 或后端服务即可运行
- 便于测试:响应内容可控,方便 UI 调试
- 架构预留:AiService 的方法签名已为真实 API 调用设计好接口,替换
getResponse方法即可接入大模型
七、构建与运行
7.1 环境要求
- DevEco Studio 5.0.3 及以上
- HarmonyOS SDK API 21(对应 HarmonyOS 6.0)
- ohpm 包管理器
7.2 模块配置
项目仅注册一个入口页面,main_pages.json 配置如下:
{
"src": [
"pages/Index"
]
}
7.3 编译运行
- 用 DevEco Studio 打开项目根目录
- 等待 Gradle/Hvigor 同步完成
- 连接 HarmonyOS 设备或启动模拟器
- 点击 Run 按钮编译运行
整个编译过程无任何错误或警告,符合 ArkTS 严格模式的所有规范要求。
八、总结与展望
本文通过一个完整的 AI 智能助手应用,展示了 HarmonyOS 6.0 + ArkTS 技术栈在实际项目中的综合运用。应用覆盖了以下核心技术点:
- 6 种状态管理装饰器:
@State、@Prop、@Link、@Provide、@Consume、@Observed、@ObjectLink - UIContext 动画系统:
animateTo、transition、animation - 流式数据渲染:回调式逐字输出 + 局部状态更新
- 持久化存储:Preferences API 实现设置跨会话保存
- 自定义弹窗:bindSheet 替代 AlertDialog
- 声明式 UI:
@Builder、@Component、ForEach、条件渲染 - 深色模式:全局状态共享 + 集中式颜色常量管理
- 严格模式合规:索引签名、生成器函数、索引访问等限制的解决方案
本项目代码结构清晰、注释完整、无编译错误,可作为 HarmonyOS 6.0 应用开发的学习参考和项目模板。后续可在此基础上扩展真实 AI 接口对接、语音输入、图片生成、历史记录管理等功能,打造一个功能完备的 AI 助手产品。
本文基于 HarmonyOS 6.0 API 21 + ArkTS 严格模式编写,所有代码均通过 DevEco Studio 编译验证。
更多推荐



所有评论(0)