鸿蒙5开发宝藏案例分享---应用架构实战技巧
【摘要】 鸿蒙应用架构实战:分层设计与线程通信详解大家好! 今天咱们聊聊鸿蒙开发中那些“官方文档提了但实际开发难找”的架构设计技巧。结合官方文档(链接1、链接2),我会用真实代码案例+通俗讲解,帮你把分层架构和线程通信落地到项目里,告别“理论会了,代码不会”的尴尬! 一、分层架构:三层设计到底怎么用?鸿蒙的分层架构(产品定制层、基础特性层、公共能力层)不是空谈,核心是降低耦合...
大家好! 今天咱们聊聊鸿蒙开发中那些“官方文档提了但实际开发难找”的架构设计技巧。结合官方文档,我会用真实代码案例+通俗讲解,帮你把分层架构和线程通信落地到项目里,告别“理论会了,代码不会”的尴尬!
一、分层架构:三层设计到底怎么用?
鸿蒙的分层架构(产品定制层、基础特性层、公共能力层)不是空谈,核心是降低耦合和多端复用。直接看代码结构:
MyApp/
│
├── entry/ # 产品定制层:设备专属入口
│ ├── phone/ # 手机端UI和逻辑
│ └── tablet/ # 平板端定制
│
├── features/ # 基础特性层:可插拔业务模块
│ ├── news/ # 新闻模块(独立HAP)
│ └── settings/ # 设置模块
│
└── common/ # 公共能力层
├── components/ # 公共UI组件
├── utils/ # 工具库
└── network/ # 网络请求封装
关键代码示例:
1. 公共能力层抽离网络请求
// common/network/Request.ts
export class Request {
static async fetch(url: string): Promise<any> {
try {
const response = await http.createHttp().request(url);
return response.data;
} catch (err) {
// 统一错误处理
console.error("Network error:", err);
}
}
}
2. 基础特性层调用公共能力
// features/news/NewsViewModel.ts
import { Request } from '../../common/network/Request';
class NewsViewModel {
async loadNews() {
const data = await Request.fetch('https://api.news.com/list');
// 业务逻辑处理...
}
}
3. 产品定制层按设备加载模块
// entry/phone/resources/base/profile/main_pages.json
{
"src": [
"pages/PhoneHome", // 手机首页
"pages/NewsPage?module=news" // 动态加载新闻模块
]
}
为什么这样设计?
- 改网络请求?只需动
common/network
,不影响业务代码。- 加新设备(如手表)?复制
entry/phone
改为entry/watch
定制UI。- 下架新闻模块?直接移除
features/news
的HAP包。
二、线程通信:子线程如何安全更新UI?
鸿蒙的UI更新必须在主线程(也叫UI线程),但耗时操作(网络请求/数据库读写)需放在子线程。官方推荐用 TaskDispatcher
和 Emitter
通信。
实战场景:子线程获取数据 → 主线程刷新UI
// 在ViewModel中
import { emitter, TaskDispatcher } from '@ohos.base';
import { Request } from '../common/network/Request';
const UI_TASK_DISPATCHER = TaskDispatcher.getGlobalTaskDispatcher(TaskDispatcher.Priority.HIGH);
class UserViewModel {
private userId: string = '';
// 1. 子线程获取数据
async fetchUserData() {
const backgroundTask: TaskDispatcher = TaskDispatcher.createBackgroundTaskDispatcher();
backgroundTask.asyncDispatch(() => {
const data = Request.fetch(`https://api.user.com/${this.userId}`);
// 2. 通过Emitter发送数据到主线程
emitter.emit('USER_DATA_LOADED', data);
});
}
// 3. 主线程监听事件
setupEventListener() {
emitter.on('USER_DATA_LOADED', (data) => {
UI_TASK_DISPATCHER.asyncDispatch(() => {
// 安全更新UI
this.userInfo = data;
AppStorage.setOrCreate('userName', data.name); // 绑定到UI组件
});
});
}
}
避坑指南:
- 错误示例:在子线程直接调
AppStorage.set()
→ 导致UI崩溃。- 正确姿势:子线程发事件 → 主线程用
asyncDispatch
更新数据。- 性能优化:高频更新?用
@State
+@Watch
局部刷新组件。
三、模块化设计:HAP、HAR、HSP怎么选?
官方文档总提这些概念,实际开发这样用:
类型 | 场景 | 代码示例 |
---|---|---|
HAP | 独立功能模块(如设置) | build-profile.json 中配置 "type": "feature" |
HAR | 公共工具库(无UI) | 被多个HAP依赖的静态库 |
HSP | 跨应用共享代码 | 声明 shared: true |
动态加载HAP模块(常见于插件化)
// 在entry中动态加载新闻模块
import featureAbility from '@ohos.ability.featureAbility';
const moduleName = 'news';
featureAbility.dynamicImport(
`bundlename:${moduleName}`,
(err, data) => {
if (err) return;
// 加载成功后跳转到新闻页
router.pushUrl({ url: 'pages/NewsPage' });
}
);
四、官方文档没明说的实战技巧
-
公共能力层防“污染”:
-
禁止上层反向依赖:
common
不能导入entry
或features
的代码。 -
检查方法:在
build-profile.json
配置依赖关系:"dependencies": { "features/news": ">=1.0.0", "common": ">=1.0.0" }
-
-
多设备适配杀手锏:
用资源限定词
区分设备,如:news_page.phone.ets
→ 手机版新闻页news_page.tablet.ets
→ 平板版(大屏布局)
编译时自动匹配设备类型打包!
结尾
鸿蒙的分层和模块化设计,初期搭建费点劲,但后期维护真香!建议大家:
- 公共代码坚决下沉到
common
层; - 子线程操作后,必须用Emitter回主线程更新UI;
- 新功能尽量拆成HAP,方便热更新。
遇到坑?欢迎留言讨论。
保持封装,拒绝耦合,咱们下期见! 🚀
【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
作者其他文章
评论(0)