
网罗开发 (小红书、快手、视频号同名)
大家好,我是 展菲,目前在上市企业从事人工智能项目研发管理工作,平时热衷于分享各种编程领域的软硬技能知识以及前沿技术,包括iOS、前端、Harmony OS、Java、Python等方向。在移动端开发、鸿蒙开发、物联网、嵌入式、云原生、开源等领域有深厚造诣。
图书作者:《ESP32-C3 物联网工程开发实战》
图书作者:《SwiftUI 入门,进阶与实战》
超级个体:COC上海社区主理人
特约讲师:大学讲师,谷歌亚马逊分享嘉宾
科技博主:华为HDE/HDG
我的博客内容涵盖广泛,主要分享技术教程、Bug解决方案、开发工具使用、前沿科技资讯、产品评测与使用体验 。我特别关注云服务产品评测、AI 产品对比、开发板性能测试以及技术报告,同时也会提供产品优缺点分析、横向对比,并分享技术沙龙与行业大会的参会体验。我的目标是为读者提供有深度、有实用价值的技术洞察与分析。
展菲:您的前沿技术领航员
👋 大家好,我是展菲!
📱 全网搜索"展菲",即可纵览我在各大平台的知识足迹。
每周定时推送干货满满的技术长文,从新兴框架的剖析到运维实战的复盘,助您技术进阶之路畅通无阻。
文章目录
-
- 引言
- 一、为什么状态管理比你想象的重要
- [二、ArkUI 的核心:State Driven UI](#二、ArkUI 的核心:State Driven UI)
- [三、@State 的底层工作机制](#三、@State 的底层工作机制)
- 四、第一个大坑:状态和普通变量混用
- [五、为什么大型项目必须引入 Store](#五、为什么大型项目必须引入 Store)
- [六、构建 UserStore](#六、构建 UserStore)
- 七、推荐的状态分层架构
- [八、为什么滥用 @Link 很危险](#八、为什么滥用 @Link 很危险)
- [九、AI App 带来的新挑战](#九、AI App 带来的新挑战)
- 十、状态持久化设计
- 十一、鸿蒙跨设备状态同步实践
- 十二、性能优化案例
- [十三、未来趋势:状态管理正在变成 Runtime 管理](#十三、未来趋势:状态管理正在变成 Runtime 管理)
- 十四、推荐项目结构
- 总结
引言
很多开发者刚开始做鸿蒙 App 时,对状态管理的理解其实非常简单。
例如:
text
点击按钮
↓
修改变量
↓
刷新页面
看起来没什么问题,甚至很多 Demo 里都是这样:
ts
@Entry
@Component
struct DemoPage {
private count: number = 0
build() {
Column() {
Text(`${this.count}`)
Button('点击')
.onClick(() => {
this.count++
})
}
}
}
结果运行以后发现:
text
页面根本不会刷新
于是很多人第一次接触 ArkUI 时都会疑惑:
text
变量变了
为什么 UI 不变?
因为在鸿蒙里:
UI 从来不是由变量驱动的。
而是驱动:
text
State
真正的大型项目里:
text
状态
=
应用运行时世界
而不是:
text
几个变量
这也是鸿蒙状态管理的核心思想。
一、为什么状态管理比你想象的重要
很多开发者理解 App:
text
页面
↓
接口
↓
数据显示
但系统真正运行时其实是:
text
Server
↓
State
↓
UI
例如一个在线学习 App:用户进入课程页面。
页面显示:
- 用户信息
- 学习进度
- 视频播放状态
- 收藏状态
- AI 助教状态
这些内容本质上都是:
text
State
UI 只是状态的一层展示,例如:
ts
interface CourseState {
courseId: string
progress: number
isFavorite: boolean
}
页面真正依赖的是:
ts
courseState
而不是:
ts
Text()
Button()
Column()
二、ArkUI 的核心:State Driven UI
ArkUI 的设计思想非常明确:
text
State
↓
Render
↓
UI
例如:
ts
@Entry
@Component
struct Counter {
@State count: number = 0
build() {
Column() {
Text(`${this.count}`)
Button("增加")
.onClick(() => {
this.count++
})
}
}
}
这里:
ts
this.count++
发生以后:
text
count变化
↓
ArkUI监听
↓
组件Dirty
↓
局部重建
↓
UI更新
开发者不用主动刷新页面,ArkUI 自动完成。这也是响应式编程最大的优势。
三、@State 的底层工作机制
很多人以为:
ts
@State count = 0
只是语法糖,实际上:
text
@State
会把变量注册到状态观察系统,例如:
ts
@State userName: string = "Tom"
当执行:
ts
this.userName = "Jack"
ArkUI 会自动记录:
text
userName发生变化
然后标记对应组件:
text
Dirty
最后执行:
text
局部刷新
而不是:
text
整个页面重绘
这也是 ArkUI 性能高的重要原因。
四、第一个大坑:状态和普通变量混用
很多项目里经常出现:
ts
@State count = 0
private loading = false
然后:
ts
this.loading = true
开发者发现:
text
UI没更新
原因很简单:
text
loading
不是状态
例如:
ts
@State loading = false
Button("加载")
.onClick(() => {
this.loading = true
})
这样页面才会刷新,经验原则:
text
参与UI渲染
必须是State
五、为什么大型项目必须引入 Store
项目初期:
ts
@State userName = "Tom"
没有问题,但项目越来越大以后:
text
首页
课程页
订单页
个人中心
AI助手
都需要访问用户信息,于是出现:
text
Props地狱
text
Page
↓
ComponentA
↓
ComponentB
↓
ComponentC
每层都要传:
ts
userInfo
维护成本极高,所以大型项目都会引入:
text
Store
六、构建 UserStore
例如:
ts
@Observed
export class UserStore {
userId: string = ''
userName: string = ''
avatar: string = ''
updateUser(name: string) {
this.userName = name
}
}
创建全局实例:
ts
export const userStore = new UserStore()
页面直接读取:
ts
@Entry
@Component
struct ProfilePage {
@ObjectLink
user = userStore
build() {
Column() {
Text(this.user.userName)
Button("修改昵称")
.onClick(() => {
this.user.updateUser("Harmony")
})
}
}
}
这时候:
text
Store变化
↓
所有依赖页面同步刷新
七、推荐的状态分层架构
大型项目推荐:
text
State
├── LocalState
├── PageState
├── GlobalState
└── DistributedState
LocalState
组件内部状态:
ts
@State expanded = false
例如:
ts
Button("展开")
.onClick(() => {
this.expanded = !this.expanded
})
适用于:
- Tab
- 折叠面板
- 弹窗
PageState
页面级状态:
ts
class CoursePageState {
currentChapter: number = 1
progress: number = 0
}
例如:
ts
coursePageState.progress = 60
仅当前页面使用。
GlobalState
全局状态,全局共享:
ts
class UserStore {
}
class MessageStore {
}
class AuthStore {
}
DistributedState
鸿蒙特有,例如:
ts
interface DeviceState {
deviceId: string
workspaceId: string
taskId: string
}
用于:
- 跨设备协同
- Workspace同步
- AI任务迁移
八、为什么滥用 @Link 很危险
很多团队为了方便:
ts
@Link userName: string
到处使用,例如:
text
PageA
↕
PageB
↕
PageC
所有组件共享同一个状态,后期经常出现:
text
用户昵称突然变化
但没人知道是谁改的,推荐:
text
默认Prop
必要时Link
例如:
ts
@Prop userName: string
优先单向数据流。
九、AI App 带来的新挑战
传统 App:
text
用户状态
订单状态
就够了。
AI App 完全不同,例如:
ts
interface AIContext {
sessionId: string
messages: Message[]
tools: ToolState[]
memory: MemoryState[]
}
用户发送消息:
ts
aiStore.messages.push(message)
不仅影响:
text
聊天窗口
还会影响:
text
Agent
Tool
Memory
整个运行时,所以未来最复杂的状态往往是:
text
AI Runtime State
十、状态持久化设计
很多项目:
text
退出App
↓
状态丢失
体验很差,推荐:
text
State
↓
Snapshot
↓
Storage
例如:
ts
class PersistenceManager {
save(state: any) {
AppStorage.SetOrCreate(
"app_state",
JSON.stringify(state)
)
}
restore() {
return JSON.parse(
AppStorage.Get("app_state")
)
}
}
启动时:
ts
const snapshot =
PersistenceManager.restore()
恢复:
text
用户状态
课程状态
AI状态
十一、鸿蒙跨设备状态同步实践
例如,用户正在手机编辑文档:
ts
interface DocumentState {
docId: string
cursor: number
content: string
}
拖到鸿蒙 PC,真正同步的是:
ts
{
docId: "001",
cursor: 120,
content: "..."
}
而不是:
text
整个页面
恢复:
ts
documentStore.restore(snapshot)
实现:
text
工作连续性
这也是鸿蒙分布式能力的核心价值。
十二、性能优化案例
很多项目:
ts
@State appState = {
user:{},
ai:{},
course:{},
message:{}
}
任何字段变化:
text
全部刷新
性能迅速下降,正确做法:
text
UserStore
CourseStore
AIStore
MessageStore
例如:
ts
class AIStore {}
class UserStore {}
这样:
text
AI变化
↓
只刷新AI模块
不会影响整个页面。
十三、未来趋势:状态管理正在变成 Runtime 管理
过去:
text
管理数据
未来:
text
管理运行时
尤其 AI Native App 出现以后,状态不再只是:
text
用户信息
而是:
text
Agent状态
Memory状态
Workspace状态
Tool状态
推理状态
例如:
ts
interface RuntimeState {
user: UserState
workspace: WorkspaceState
ai: AIContext
memory: MemoryState
}
最终:
text
State
=
Runtime
十四、推荐项目结构
text
state/
├── user/
│ ├── UserStore.ts
│ └── UserAction.ts
│
├── course/
│ ├── CourseStore.ts
│ └── CourseAction.ts
│
├── ai/
│ ├── AIStore.ts
│ ├── SessionStore.ts
│ └── MemoryStore.ts
│
├── distributed/
│ ├── DeviceStore.ts
│ ├── WorkspaceStore.ts
│ └── RuntimeStore.ts
│
└── persistence/
├── Snapshot.ts
└── Recovery.ts
核心原则:
text
UI 不管理状态
而是:
text
UI 消费状态
总结
如果一句话总结鸿蒙 App 状态管理:
页面只是状态的投影。
真正重要的从来不是:
- 页面怎么刷新
- 组件怎么通信
而是:
text
状态如何组织
包括:
- Local State
- Global State
- AI State
- Distributed State
- Runtime State
很多团队做到后期都会发现:
text
App 越复杂
状态越重要
因为真正驱动鸿蒙应用运行的,不是页面,而是:
text
State Runtime
未来的鸿蒙 App,尤其是 AI Native App,管理的已经不只是数据。而是:
text
整个应用运行时世界
所以状态管理的终点,从来不是 Store。而是:
text
Runtime。