写点什么

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

作者:莓创技术
  • 2025-06-17
    广东
  • 本文字数:2201 字

    阅读完需:约 7 分钟

鸿蒙应用架构实战:分层设计与线程通信详解

​大家好!​​ 今天咱们聊聊鸿蒙开发中那些“官方文档提了但实际开发难找”的架构设计技巧。结合官方文档(链接 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 线程),但耗时操作(网络请求/数据库读写)需放在子线程。官方推荐用 TaskDispatcherEmitter 通信。

实战场景:子线程获取数据 → 主线程刷新 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 模块(常见于插件化)​


// 在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. ​公共能力层防“污染”​​:

  2. 禁止上层反向依赖:common 不能导入 entryfeatures 的代码。

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


        "dependencies": {            "features/news": ">=1.0.0",            "common": ">=1.0.0"          }  
复制代码


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

  2. 资源限定词 区分设备,如:

  3. news_page.phone.ets → 手机版新闻页

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

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



结尾

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


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

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

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


遇到坑?欢迎留言讨论。


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

用户头像

莓创技术

关注

一只会打代码的羊 2020-03-20 加入

还未添加个人简介

评论

发布
暂无评论
鸿蒙5开发宝藏案例分享---应用架构实战技巧_莓创技术_InfoQ写作社区