一、MVVM模式

应用通过状态去渲染更新UI是程序设计中相对复杂,但又十分重要的,往往决定了应用程序的性能。程序的状态数据通常包含了数组、对象,或者是嵌套对象组合而成。在这些情况下,ArkUI采取MVVM = Model + View + ViewModel模式,其中状态管理模块起到的就是ViewModel的作用,将数据与视图绑定在一起,更新数据的时候直接更新视图。

  • Model层:存储数据和相关逻辑的模型。它表示组件或其他相关业务逻辑之间传输的数据。Model是对原始数据的进一步处理。

  • View层:在ArkUI中通常是@Component装饰组件渲染的UI。

  • ViewModel层:在ArkUI中,ViewModel是存储在自定义组件的状态变量、LocalStorage和AppStorage中的数据。

    • 自定义组件通过执行其build()方法或者@Builder装饰的方法来渲染UI,即ViewModel可以渲染View。

    • View可以通过相应event handler来改变ViewModel,即事件驱动ViewModel的改变,另外ViewModel提供了@Watch回调方法用于监听状态数据的改变。

    • 在ViewModel被改变时,需要同步回Model层,这样才能保证ViewModel和Model的一致性,即应用自身数据的一致性。

    • ViewModel结构设计应始终为了适配自定义组件的构建和更新,这也是将Model和ViewModel分开的原因。

目前很多关于UI构造和更新的问题,都是由于ViewModel的设计并没有很好的支持自定义组件的渲染,或者试图去让自定义组件强行适配Model层,而中间没有用ViewModel来进行分离。例如,一个应用程序直接将SQL数据库中的数据读入内存,这种数据模型不能很好的直接适配自定义组件的渲染,所以在应用程序开发中需要适配ViewModel层。

img

根据上面涉及SQL数据库的示例,应用程序应设计为:

  • Model:针对数据库高效操作的数据模型。

  • ViewModel:针对ArkUI状态管理功能进行高效的UI更新的视图模型。

  • 部署 converters/adapters: converters/adapters作用于Model和ViewModel的相互转换。

    • converters/adapters可以转换最初从数据库读取的Model,来创建并初始化ViewModel。

    • 在应用的使用场景中,UI会通过event handler改变ViewModel,此时converters/adapters需要将ViewModel的更新数据同步回Model。

虽然与强制将UI拟合到SQL数据库模式(MV模式)相比,MVVM的设计比较复杂,但应用程序开发人员可以通过ViewModel层的隔离,来简化UI的设计和实现,以此来收获更好的UI性能。

二、分层架构设计

企业级项目分析

har hsp hap

https://gitee.com/harmonyos_codelabs/MultiVideoApplication/tree/master

https://gitee.com/harmonyos_codelabs/MusicHome

https://developer.huawei.com/consumer/cn/codelabsPortal/carddetails/tutorials_Next-BasicArchitectureDesignPart2

https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/application-dev-guide-0000001630265101

概述

HarmonyOS应用的分层架构设计以一套代码工程为基础,旨在为华为的手机、2in1等1+8全场景设备提供支持,实现了“一次开发,多端部署”的开发理念。

HarmonyOS应用的分层架构主要包括三个层次:产品定制层、基础特性层和公共能力层,为开发者构建了一个清晰、高效、可扩展的设计架构。

分层思想

图1 分层架构逻辑模型

点击放大

  • 产品定制层

    产品定制层专注于满足不同设备或使用场景(如应用)的个性化需求,包括UI设计、资源和配置,以及针对特定场景的交互逻辑和功能特性。

    产品定制层的功能模块独立运作,同时依赖基础特性层和公共能力层来实现具体功能。

    作为应用的入口,产品定制层是用户直接互动的界面。为满足特定产品需求,产品定制层可灵活地调整和扩展,从而满足各种使用场景。

  • 基础特性层

    基础特性层位于公共能力层之上,用于存放基础特性集合,例如相对独立的功能UI和业务逻辑实现。该层的每个功能模块都具有高内聚、低耦合、可定制的特点,以支持产品的灵活部署。

    基础特性层为上层的产品定制层提供稳健且丰富的基础功能支持,包括UI组件、基础服务等。同时依赖于下层的公共能力层为其提供通用功能和服务。

    为了增强系统的可扩展性和维护性,基础特性层将功能进行模块化处理。例如,一个应用的底部导航栏中的每个选项都可能是一个独立的业务模块。

  • 公共能力层

    公共功能层用于存放公共基础能力,集中了例如公共UI组件、数据管理、外部交互以及工具库等的共享功能。应用可以共享和调用这些公共能力。

    公共能力层为上层的基础特性层和产品定制层提供稳定可靠的功能支持,确保整个应用的稳定性和可维护性。

    公共能力层包括但不限于以下组成:

    • 公共UI组件:这些组件被设计成通用且高度可复用的,确保在不同的应用程序模块间保持一致的用户体验。公共UI组件提供了标准化且友好的界面,帮助开发者快速实现常见的用户交互需求,例如提示、警告、加载状态显示等,从而提高开发效率和用户满意度。

    • 数据管理:负责应用程序中数据的存储和访问,包括应用数据、系统数据等,提供了统一的数据管理接口,简化数据的读写操作。通过集中式的数据管理方式不仅使得数据的维护更为简单,而且能够保证数据的一致性和安全性。

    • 外部交互:负责应用程序与外部系统的交互,包括网络请求、文件I/O、设备I/O等,提供统一的外部交互接口,简化应用程序与外部系统的交互。开发者可以更为方便地实现应用程序的网络通信、数据存储和硬件接入等功能,从而加速开发流程并保证程序的稳定性和性能。

    • 工具库:提供一系列常用工具函数和类,例如字符串处理、日期时间处理、加密解密、数据压缩解压等,帮助开发者提高效率和代码质量。

架构思想

图2 分层架构开发模型

  • 产品定制层

    产品定制层的各个子目录会被编译成一个Entry类型的HAP,作为应用的主入口。该层主要针对跨多种设备,为各种设备形态集成相应的功能和特性。产品定制层被划分为多个功能模块,每个功能模块都针对特定的设备或使用场景设计,并根据具体的产品需求进行功能及交互的定制开发。

    说明

    • 在产品定制层,开发者可以从不同设备对应应用的UX设计和功能两个维度,结合具体的业务场景,选择一次编译生成相同或者不同的HAP(或其组合)

    • 通过使用定制多目标构建产物的定制功能,可以将应用所对应的HAP编译成各自的.app文件,用于上架到应用市场。

  • 基础特性层

    在基础特性层中,功能模块根据部署需求被分为两类。对于需要通过Ability承载的功能,可以设计为Feature类型的HAP,而对于不需要通过Ability承载的功能,根据是否需要实现按需加载,可以选择设计为HAR模块或者HSP模块,编译后对应HAR包或者HSP包。

  • 公共能力层

    公共能力层的各子目录将被编译成HAR包,而他们只能被产品定制层和基础特性层所依赖,不允许存在反向依赖。该层旨在提取模块化公共基础能力,为上层提供标准接口和协议,从而提高整体的复用率和开发效率。

部署结构

安卓 .apk

IOS .ipa

HM .app

图3 分层架构部署模型(不同设备的定制)

点击放大

应用程序(.app文件)在流水线或应用市场上被解包为n * Entry类型的HAP + n * Feature类型的HAP,根据设备类型和使用场景将应用部署到不同类型的设备上,实现多端的统一用户体验。

说明

当Entry类型的HAP和Feature类型的HAP被分发并部署到相应的设备时,他们所依赖的HSP也会一同被分发并部署到相应的设备上。

在部署模型中,每个Entry类型的HAP代表了应用的入口点,而Feature类型的HAP则包含了应用的特定功能模块。允许应用能够以模块化的方式适配和部署,从而满足不同设备和场景的需求。

该部署模型不仅优化了应用的组织结构,也为保持应用在各种设备和场景中的一致性提供了支持。通过按照设备类型和使用场景来区分和部署不同的HAP,能确保无论在何种设备或场景中,用户都能获得统一且高质量的体验。

模块种类

1 就是三个普通目录 里面放n个目录 更符合鸿蒙 一次开发 多端部署的思想 万物互联

2 common har features feature.hap/har/hsp products entry.hap

1、har跟随使用方编译,多个使用方,会生成多份相同拷贝;hsp独立编译运行时在一个进程中代码也只会存在一份;

2、har可以作为二方库、三方库;

作为二方库,发布到OHPM私仓,供公司内部其他应用使用。 作为三方库,发布到OHPM中心仓,供其他应用使用。

实战演练

  • 创建deveco项目 three

  • 创建分层结构 common features products

  • 移动entry到products目录 可以改名也可以不改 (以后你看到 products目录续爱 default/entry 其实都是指phone设备)

  • 分别在

products 创建  twoInOne产品线      entry模块   .hap
common   创建 har
    components
    utils
    data
features 创建  feature.hap/.har/.hsp

跨模块跳转&传参

entry 跳转 hsp

router.pushUrl({
  url: '@bundle:com.samples.hspsample/library/ets/pages/Menu'
  url: '@bundle:项目唯一标识就跟你身份证一样/library/ets/pages/Menu'
  url: '@bundle:包名(bundleName)/模块名(moduleName)/路径/页面所在的文件名(不加.ets后缀)'
})
​
项目唯一标识就跟你身份证一样  根目录/AppScope/app.json5   bundleName     com.example.three    用于后期推送消息、广告投放等等

entry 跳转 har

1、给har模块 加一个路由名字    @Entry({ routeName: 'myPage' })
​
​
2、hap包导入命名的路由   
- 2.1 配置下  开发三方库有关
- 2.2 再导入  import('@ohos/library/src/main/ets/pages/Index');  // 引入共享包中的命名路由页面
​
​
"dependencies": {
  "@ohos/har1": "file:../../features/har1"
}
​
import('@ohos/har1/src/main/ets/components/MainPage');  // 引入共享包中的命名路由页面
​
​
​
​
3、跨模块/包跳转并传参
​
router.pushNamedRoute({   
        name: 'myPage',
        params: {
          data1: 'message',
          data2: {
            data3: [123, 456, 789]
          }
        }
      })
​

hsp、har 跳转 entry

router.repalceUrl({   
    url: 'pages/Index'
})

如果一个工程在同一个设备存在多个模板(例如手机设备上,存在entry和feature模块),且模块间存在调用关系,那么在调试时需要安装多个模块的hap包都设备上。此时,需要在待调试模块的设置项中勾选“Deploy Multi Hap Packages”。例如,entry模块调用了feature模块,那么调试entry模块时,需要同时安装feature模块,则需要勾选“Deploy Multi Hap Packages”再启动调试。

知识点总结

1、MVVM M 数据模型、V @Component 里面build 视图 VM组件状态、全局应用状态

2、分层架构设计

- 2.1  三个空目录   products entry.hap    features  feature.hap/har/hsp    common  har
- 2.2  独立在每个目录创建这些模块     并且知道开发态、到编译态     hap/hsp都是独立的,har根据使用方编译 让项目体积变大
- 2.3  跨模块跳转
entry hsp        router.pushUrl  url   '@bundle:包名/模块名/路径/页面所在的文件名(不加.ets后缀)'
entry har                router.pushNamedRoute 
hsp/har entry    router.pushUrl  url

三、企业级面试题&场景

MVVM模式

谈谈你对MVVM理解(概率低)

  • VUE:M模式主要负责数据管理,V是视图主要负责页面展示,VM是M和V之间的桥梁当数据变化会同步到视图

  • HM:M就是存储数据和相关逻辑的模型,V在ArkUI中通常是@Component装饰组件渲染的UI, VM在ArkUI中,ViewModel是存储在自定义组件的组件状态、和应用状态。


  • VUE中(一个文件) : M代表模型 管理数据 就是响应是数据 data/ref/reactive、 V代表视图 展示数据 VM M和V之间的桥梁

  • HM中

M  之前项目写类型 types   model目录  数据结构  class  UserItemType
V  @Component  build  展示数据
VM  @State/@StroageLink
​
​
- Model:针对数据库高效操作的数据模型。
- ViewModel:针对ArkUI状态管理功能进行高效的UI更新的视图模型。
- 部署 converters/adapters: converters/adapters作用于Model和ViewModel的相互转换。
  - converters/adapters可以转换最初从数据库读取的Model,来创建并初始化ViewModel。
  - 在应用的使用场景中,UI会通过event handler改变ViewModel,此时converters/adapters需要将ViewModel的更新数据同步回Model。
  • MVC模式(三个目录):前后端不分离时代

M 模型 专门操作数据库的  其实就是目录专门放操作数据库的文件、
V 视图展示数据给用户,其实就是一个目录  专门放前端html文件的     =》  模版引擎   指定标签可以获取后端代码 
C 控制器     用户访问路由   他来控制调用哪一个M  调用哪一个V
  • 鸿蒙分层架构设计/三层架构

https://developer.huawei.com/consumer/cn/codelabsPortal/carddetails/tutorials_Next-BasicArchitectureDesignPart2

common    公共代码   
features  业主代码
products  各种设别   移动端、2和1设备、智能穿戴

分层架构设计

静态包har和动态包hsp的区别

1、har跟随使用方编译,多个使用方,会生成多份相同拷贝;hsp独立编译运行时在一个进程中代码也只会存在一份;
2、har可以作为二方库、三方库;


作为二方库,发布到OHPM私仓,供公司内部其他应用使用。
作为三方库,发布到OHPM中心仓,供其他应用使用。

你了解 hsp 和 hap 包的区别吗

hap 应用的功能模块,可以独立安装和运行,必须包含一个entry类型的HAP,可选包含一个或多个feature类型的HAP。
hsp 动态共享包,运行时复用。

你当时做的是 hsp har 的

都有

跨模块跳转传参

跳转hsp
router.pushUrl({
  url: '@bundle:com.samples.hspsample/library/ets/pages/Menu'
  url: '@bundle:项目唯一标识就跟你身份证一样/library/ets/pages/Menu'
  url: '@bundle:包名(bundleName)/模块名(moduleName)/路径/页面所在的文件名(不加.ets后缀)'
})

跳转har
router.pushNamedRoute({    name: 'myPage', params: {}   })

跨模块资源访问有了解过吗

通过$r/$rawfile的形式引用应用资源  一样的

欢迎加入课程班级,考取鸿蒙认证:

https://developer.huawei.com/consumer/cn/training/classDetail/d43582bb30b34f548c16c127cb3be104?type=1?ha_source=hmosclass&ha_sourceId=89000248
 

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐