首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >鸿蒙5开发宝藏案例分享---应用架构实战技巧

鸿蒙5开发宝藏案例分享---应用架构实战技巧

原创
作者头像
陈杨
修改2025-06-27 17:08:15
修改2025-06-27 17:08:15
3060
举报

​**​大家好!​**​ 今天咱们聊聊鸿蒙开发中那些“官方文档提了但实际开发难找”的架构设计技巧。结合官方文档,我会用​**​真实代码案例+通俗讲解​**​,帮你把分层架构和线程通信落地到项目里,告别“理论会了,代码不会”的尴尬!

* * *

一、分层架构:三层设计到底怎么用?

鸿蒙的分层架构(产品定制层、基础特性层、公共能力层)不是空谈,核心是​**​降低耦合​**​和​**​多端复用​**​。直接看代码结构:

```

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' });

}

);

```

* * *

四、官方文档没明说的实战技巧

1. ​**​公共能力层防“污染”​**​:

- 禁止上层反向依赖:`common` 不能导入 `entry` 或 `features` 的代码。

- 检查方法:在 `build-profile.json` 配置依赖关系:

```

"dependencies": {

"features/news": ">=1.0.0",

"common": ">=1.0.0"

}

```

1. ​**​多设备适配杀手锏​**​:

用 `资源限定词` 区分设备,如:

- `news_page.phone.ets` → 手机版新闻页

- `news_page.tablet.ets` → 平板版(大屏布局)

编译时自动匹配设备类型打包!

* * *

结尾

鸿蒙的分层和模块化设计,初期搭建费点劲,但后期维护真香!建议大家:

1. 公共代码坚决下沉到 `common` 层;

1. 子线程操作后,​**​必须用Emitter回主线程更新UI​**​;

1. 新功能尽量拆成HAP,方便热更新。

遇到坑?欢迎留言讨论。

​**​保持封装,拒绝耦合,咱们下期见!​**​ 🚀

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档