HarmonyOS 应用开发指南(一)

HarmonyOS 和 OpenHarmony

HarmonyOS 演进

  1. 2019年8月华为发布了 HarmonyOS 1.0 并运用在智慧屏产品;

  2. 2020年9月华为发布了 HarmonyOS 2.0 版本,囊括了更多设备类型,如智能穿戴、车机等,对应的 HarmonyOS SDK 版本为 API Version 3。同时华为面向第三方设备发布了 HarmonyOS 开源版本;在此后的一年中不断迭代 2.x 版本,此时的 HarmonyOS 基于 Java 和 JavaScript 语言进行应用层开发;

  3. 2021年10月份,HarmonyOS 更新至 3.0 版本,该版本有了较大变化,JS UI更名为 ArkUI,并在原有基于 JS扩展的类 Web 开发范式上发布基于 TS 扩展的声明式UI开发范式,支持了 TypeScript,并完善了一系列 JS接口。详细内容可关注官方文档;

  4. 2022年11月迭代至 HarmonyOS 3.1 版本,首次推出了 Stage 应用模型,并增强了 ArkTS、应用程序框架和ArkUI等子系统能力。

  5. HarmonyOS Next :余承东在 2023年9月份公布华为将在 2024年推出 HarmonyOS Next 版本,该版本将不再兼容 Android 应用。此外根据官方说法,Stage 模型 将会是 官方长期支持的应用开发模型。HarmonyOS Next 版本的SDK和文档目前未对外公布,但是企业可以向华为的接口对接人申请。

HarmonyOS 和 OpenHarmony 的关系

2020年9月,华为向开放原子开源基金会捐赠了 HarmonyOS 2.x 版本,随后进行开源,被命名为 OpenAtom OpenHarmony,OpenHarmony 是其简称。
2020 年 12 月,博泰、华为、京东、润和、亿咖通、中科院软件所、中软国际等七家单位在开放原子开源基金会的组织下成立了 OpenHarmony 项目群工作委员会,开始对 OpenHarmony 项目进行开源社区治理。各家单位对 OpenHarmony 开源项目持续投入和贡献。

目前 OpenHarmony 接受企业、机构和个人贡献者参与共建,OpenHarmony 遵循 Apache 2.0 开源协议。

HarmonyOS 系统与Android系统类似,可分为两部分 OpenHarmony 和 HMS。前者和Android系统的 AOSP 承担相同职责,面向所有人开源。后者和 GMS 一样,如果应用需要接入推送等功能时,就需要集成 HMS相关能力。

目前 OpenHarmony 已经迭代至 v4.0 release,在开发鸿蒙应用时,只能看到系统提供的接口能力声明,如果要查看相关实现就需要下载对应的源码。

推荐和源码下载

OpenHarmony 提供了多种下载方式,具体可看 [OpenHarmony 源码传送门](zh-cn/device-dev/get-code/sourcecode-acquire.md · OpenHarmony/docs - Gitee.com),如果只想要下载 ArkUI 部分实现,可以仅下载该部分的源码,[ArkUI 源码传送门](ArkUI-X: ArkUI-X扩展ArkUI开发框架到多个OS平台, 让开发者基于一套主代码, 就可以构建支持多平台的精美、高性能应用。The ArkUI-X project extends the ArkUI framework to multiple OS platforms. This enables developers to use one main set of code to develop applications for multiple OS platforms. (gitee.com))。不过感到意外又在情理之中的是,ArkUI-X 将会扩展到多个 OS 平台,如 Android 、IOS等, 但目前它似乎还是不如 JetPack Compose 更具吸引力,前路且长啊。

HarmonyOS Next 尚在保密阶段,此外华为限制了登录时间极其短暂,OpenHarmony 则提供了更好的使用体验,而且 OpenHarmony 已迭代至 V 4 版本(截止2024年1月4日)。

以下是一些推荐的站点:

  1. OpenHarmony 官方文档\]([OpenAtom OpenHarmony](https://link.juejin.cn?target=https%3A%2F%2Fwww.openharmony.cn%2Fdocs%2Fzh-cn%2Fapplication-dev%2F "https://www.openharmony.cn/docs/zh-cn/application-dev/"))

  2. OpenHarmony Laval 问题社区\]([Laval社区 (csdn.net)](https://link.juejin.cn?target=https%3A%2F%2Flaval.csdn.net%2F "https://laval.csdn.net/")) ,目前看是比较纯粹干净的社区,希望CSDN不要玩坏了

应用模型介绍

应用模型是HarmonyOS为开发者提供的应用程序所需能力的抽象提炼,它提供了应用程序必备的组件和运行机制。有了应用模型,开发者可以基于一套统一的模型进行应用开发,使应用开发更简单、高效。

根据华为官方解释,应用模型由 应用组件、进程/线程/任务管理模型 以及应用配置文件构成。应用组件是构建应用的基本组成单位,如 Ability,页面组件等;而其他几个模型则需要关注其创建/销毁和通信方式。而应用的配置文件则涵盖了应用组件信息、权限、编译构建、开发者自定义等信息。

Stage 应用模型

目前华为主推的应用模型是 Stage 模型(HarmonyOS 3.1 Developer Preview版本开始新增的模型),该模型提供了AbilityStage、WindowStage等类作为应用组件和Window窗口的"舞台"。Stage 模型的设计出发点有3个:

  1. 为复杂应用设计:采用面向对象编程,多组件共用同一个 ArkTs 引擎

  2. 支持多设备和多窗口形态:将应用组件和窗口的形态进行了架构层面的解耦;

  3. 平衡应用能力和系统管控成本:提供多种特定场景的应用组件,严格的进程管理。

Stage 模型概念图:

应用组件

在 Stage 模型中,HarmonyOS 提供 UIAbility 和 ExtensionAbility (及其子组件)组件,前者是包含UI界面的应用组件,而后者则是特定场景的扩展组件,每个场景对应一个 [ExtensionAbilityType](@ohos.bundle.bundleManager (bundleManager模块)-包管理-ArkTS接口参考-ArkTS API参考 | 华为开发者联盟 (huawei.com)),各类型的 ExtensionAbility 组件均由相应的系统服务统一管理。FormExtensionAbility 、WorkSchedulerExtensionAbility 均是 ExtensionAbility 在不同场景的特定扩展,前者提供服务卡片相关场景,后者用于延迟任务相关能力。

窗口管理

每个UIAbility类实例都会与一个WindowStage类实例绑定,该类提供了应用进程内窗口管理器的作用。它包含一个主窗口。也就是说UIAbility通过WindowStage持有了一个窗口,该窗口为ArkUI提供了绘制区域。

若想要创建新的子窗口,就必须借助 WindowStage 来创建。

AbilityStage

鸿蒙应用在首次启动时,首先会创建一个AbilityStage实例,它和该应用(hap)内的所有UIAbility 关联,因此可以借助 AbilityStage 获取当前 hap 中 UIAbility 实例的运行时信息。

上下文

Context 和其派生类向开发者提供在运行期可以调用的各种能力,比如访问应用资源管理器、UIAbility 启动跳转等。UIAbility 和 ExtensionAbility 的派生类都有各自不同的 Context 上下文。Context 是它们共同的基类。

除了上面的内容,Stage模型还包括 进程/线程模型以及配置文件,配置文件后续会有谈到。

注:Stage 模型和早期的 FA 模型有较大的区别,官方已不再主推 FA 模型,详细内容可关注官方文档,传送门

ArkTs 和 ArkUI

ArkTs 基于 TypeScript 并进一步拓展了声明式UI范式状态管理 以及渲染控制能力。ArkTS 可直接构建页面组件,并定义了声明式UI描述。

和 JetPack Compose、Flutter 一样, ArkTs 支持以函数式编程方式构建页面组件,构建页面的函数不需要有返回值,但是必须有特定页面组件描述符进行声明,这样框架才会将其构建为UI组件。

例如 使用 @Componen 和 struct 关键字来标识一个自定义页面组件,加上 @Entry 后可表示该组件是一个自定义入口组件,组件必须重写 build 函数来搭建页面组件的内容。

此外还可以使用 @Builder / @BuilderParam 构建细粒度的可复用的组件,而这部分就需要在函数中完成。

声明式UI的需要借助状态来驱动界面所展示的元素变化。ArkTs 提供了 @State、@Prop、@Link 等状态装饰器,这些声明符修饰的变量就是状态变量,界面组件会依赖对应的状态变量,当状态值变更时,相应的UI元素就需要重绘。例如 @State 修饰的变量被 Text 组件依赖用于显示文字内容,变量值一旦修改,依赖其的 Text 组件就会更新展示的内容,而状态驱动UI更新的具体工作,则在框架层实现,开发者无需实现这些工作。

关于 ArkTs 的语法和更多使用方式,可关注官方文档了解。

声明式UI范式

声明式UI注重结果而非过程,它会告诉你它要什么,但是却不会要求你必须按照特定的步骤实现UI的更新。

关于 UI 我们需要关注 2 点:UI 组件的构建 和 UI 组件的更新

而声明式UI的做法是,在构建页面组件方面开发者需要使用特定的组件声明结合UI框架提供的多种基础组件或容器组件,并基于函数式编程来构建对应的页面组件

在UI更新方面,由状态驱动,不同状态对应了不同的UI组件或UI组件属性,UI组件需要和状态变量产生依赖,当状态值变化时,依赖其的页面组件将会重新构建或重新绘制。状态变化之所以能驱动UI更新,一是UI框架可以识别不同的状态声明,二是UI框架根据这些状态变量去更新依赖这些状态的相应组件。

此外UI组件的变化或事件也可能会影响到状态的更新。

通过声明式UI,开发者可以及其方便的构建可复用的UI组件,代码的可维护性大大提升。大量的UI组件和UI组件更新的相关实现被转移到框架中,基础组件还可以将状态提升到合适的父级别组件中,这样就可以构建可复用,与业务代码耦合度低的UI。

UIAbility

UIAbility 组件是一种包含UI界面的应用组件(由 @Entry 修饰的页面组件),主要用于和用户交互。它通过 WindowStage 为应用提供绘制UI元素的窗口,每个UIAbility 组件可以通过多个页面组件实现特定功能模块。

UIAbility 需要在应用的 module.json5 中 abilities 标签内配置。此外UIAbility 由其上下文 context 启动,启动时还可以指定启动模式,有三种启动模式可选(在abilities 标签中配置):

  • singleton: 多次启动目标 UIAbility 时,只会有一个 UIAbility 实例存在,后续启动时该组件不会重新创建,而是进入 onNewWant 回调

  • multiton:多次启动会启动多个 UIAbility 实例

  • specified:指定实例模式是针对特殊场景的。创建 specified 模式的 UIAblity 前(首次启动),开发者可以指定一个唯一的 字符串作为 key 来标识它,后续启动该 UIAbility 时,应用的 AbilityStage 的 onAcceptWant 函数会被回调,该回调函数解析启动函数的want 参数,根据业务需要返回一个字符串 key 标识。若该函数返回的 key 对应一个已经启动的 UIAbility,就会将之前已启动的 UIAbility 拉回前台重新获取焦点;若 key 未对应已启动的 UIAbility,则新建一个 UIAbility。

启动模式-官方文档传送门

状态管理

状态是指驱动UI更新的数据。用户通过触发组件的事件方法,改变状态数据。状态数据的改变,引起UI的重新渲染。

在声明式UI编程框架中,UI是程序状态的运行结果,用户构建了一个UI模型,其中应用的运行时的状态是参数。当参数改变时,UI作为返回结果,也将进行对应的改变。这些运行时的状态变化所带来的UI的重新渲染,在ArkUI中统称为状态管理机制。

常规变量结合(被状态装饰器修饰)状态装饰器,构成状态变量,状态变量的原始来源被称为数据源,数据源可以是父组件传递给子组件的数据,它还可以同步给不同的状态数据。

ArkUI 提供了多种状态装饰器,使用这些装饰器可以实现观察组件内状态变化、多层级、跨组建层级或全局范围的状态变化。此外这些装饰器还可以实现单向或双向的状态同步。

应用和页面组件的状态管理:

ArkUI 中的状态分为组件状态管理和应用状态管理。

组件状态管理:

  • @State:修饰的变量称为状态,当状态发生变化时,依赖它的其他状态的UI都会变化;必须在本地初始化,还可以通过命名参数从父组件完成初始化;其生命周期和所属的自定义组件相同,私有,仅允许组件内被访问;
  • @Prop:实现父组件 -> 子组件的单向状态同步,子组件内可以修改 其状态值,但不会影响父组件内的状态,但父组件传递而来的状态会覆盖子组件对其修改的结果
  • @Link:实现父组件和子组件双向状态同步, 需要在父组件中初始化一个 @State,在子组件中使用 定义 @Link 修饰的状态,并通过命名参数从父组件完成初始化
  • @Provider 和 @Consume: @Provider 修饰的状态对其所有子组件可用,@Provider 还可以指定参数作为别名,@Consume 修饰的状态可通过变量名和别名区分关联的状态,@Consume 在子组件中定义,与父组件中提供的状态进行双向关联
  • @Observed 和 @ObjectLink:用于嵌套对象或数组场景的双向同步。被 @Observed 修饰的类、对象可以被观察到其属性变化,但其属性的属性(嵌套对象的属性)如果没有被其修饰,就不会被观察到变化。@ObjectLink 修饰的变量用于接收前者观察的状态的变化

应用状态管理:

  • LocalStorage :页面级UI状态存储,通常用于UIAbility内、页面间的状态共享,状态存储于内存中
  • AppStorage:特殊的单例LocalStorage对象,由UI框架在应用程序启动时创建,为应用程序UI状态属性提供中央存储
  • PersistentStorage:持久化存储UI状态,通常和AppStorage配合使用,选择AppStorage存储的数据写入磁盘,以确保这些属性在应用程序重新启动时的值与应用程序关闭时的值相同;
  • Environment: 应用程序运行的设备的环境参数,环境参数会同步到AppStorage中,可以和AppStorage搭配使用
渲染控制

在自定义组件时,可借助 if-else 渲染控制语句 控制是否渲染某些组件,使用 ForEach 或 LazyForEach 基于数组快速生成组件或以懒加载方式生成组件。

ArkUI 更新优化

ArkUI 在API9上优化了相关UI更新机制,当自定义组件的某个状态变量发生变化导致自定义组件重新渲染时,仅执行该自定义组件build函数中的部分UI描述(使用了该状态变量的内置UI组件的UI描述)来实现更高性能的UI更新。而API8及以前在状态变量发生变化时会执行build函数中的全量UI描述来实现UI更新。

生命周期

UIAbility 生命周期

UIAbility 组件为应用提供绘制UI内容的窗口(在 onWindowStageCreate 回调中通过 windowStage 去加载页面UI),每个 UIAbility 对应一个鸿蒙应用中最近任务列表中的一个任务。

WindowStage 是窗口管理器,应用通过它可以实现获得主窗口,子窗口,创建窗口等操作,而 UIAbility 所加载的页面组件需要绘制到窗口中才能在屏幕上展示出来。

上图是 UIAbility 的生命周期状态,每个状态还对应一个生命周期函数: onCreate、onForeground、onBackground、onDestroy。

onCreate 和 onDestroy 分别是当前 UIAbility 刚刚创建和销毁时触发的生命周期回调函数。onForeground、onBackground 则是 UIAbility 切换至前后台时对应的回调函数,可以用于在各自状态时 UIAbility 申请或释放相应的资源。

但上面的状态又是不完整的,每个 UIAbility 在创建后,在进入 Foreground 状态前,系统会为其创建一个 WindowStage 本地窗口管理器,然后在 UIAbility 进入 destroy 状态前先销毁这个窗口管理器,对应到 UIAbility 的生命周期中,如下图所示:

UIAbility 生命周期 - 官方文档传送门

页面组件生命周期

页面组件是由 @Component 或 @Component + @Entry 修饰的UI单元,前者修饰的可以称为自定义组件,后者修饰是一个入口页面,一个入口页面可以由多个 @Component 修饰的自定义组件构成,或可以被多个 @Component 修饰的自定义组件替换 。

只有被 @Entry 修饰的页面组件才会拥有生命周期,被执行路由导航等操作。

由 @Entry 修饰的页面组件才具有 onPageShow/onPageHide 生命周期(页面显示或隐藏场景),仅被 @Component 修饰的页面组件只能感知页面自定义组件创建实例和销毁实例的生命周期函数 aboutToAppear 和 aboutToDisappear, @Entry 修饰的页面组件支持这两对页面生命周期函数。

onBackPress 函数属于@Entry 页面组件生命周期函数。

页面路由

HarmonyOS 提供了 ohos.router 用于实现页面切换跳转,Router 模块有2种跳转模式,router.pushUrl 和 router.replaceUrl ,前者将页面压入页面栈中,后者会替换然后销毁掉掉当前页面。

除了页面切换,router 还支持页面切换或返回时传递参数,参数可以指定给 router.pushUrl 或 replaceUrl 的 params 形参,然后在接收页面使用 router.getParams 获取传递的参数。

需要注意的是,在使用路由切换页面时,可以通过 router.RouterMode.Single/Standard 实现不同的效果,Standard 是标准实例模式,也是默认的模式,每当调用 pushUrl 且设置为该模式时,就会新建一个目标页压入栈顶; Single 是单实例模式,若页面栈已存在相同路由url 的目标页,距离栈顶最近的相同URL页面会被移动到栈顶并重新加载,否则按照标准实例模式执行跳转。

HarmonyOS Demo 应用

前阵子写了一个 HarmonyOS 应用 demo 已在 Gitee 上公开,基于 HarmonyOS 3.1/4.0 的API,采用 Stage 应用模型。该应用提供简单的新闻阅览效果,在技术方面涵盖了以下内容:

  1. ArkUI 页面和自定义组件开发以及各种 ArkUI 组件的使用
  2. 多媒体播放、传感器使用
  3. 多 target 和 product 配置和构建
  4. 服务卡片实现
  5. 状态管理、页面路由、内容分享等

HarmonyOS News 项目传送门

相关推荐
遇到困难睡大觉哈哈18 分钟前
HarmonyOS —— Remote Communication Kit 拦截器(Interceptor)高阶定制能力笔记
笔记·华为·harmonyos
遇到困难睡大觉哈哈2 小时前
HarmonyOS —— Remote Communication Kit 定制处理行为(ProcessingConfiguration)速记笔记
笔记·华为·harmonyos
氤氲息2 小时前
鸿蒙 ArkTs 的WebView如何与JS交互
javascript·交互·harmonyos
遇到困难睡大觉哈哈2 小时前
HarmonyOS支付接入证书准备与生成指南
华为·harmonyos
赵浩生2 小时前
鸿蒙技术干货10:鸿蒙图形渲染基础,Canvas绘图与自定义组件实战
harmonyos
赵浩生2 小时前
鸿蒙技术干货9:deviceInfo 设备信息获取与位置提醒 APP 整合
harmonyos
BlackWolfSky2 小时前
鸿蒙暂未归类知识记录
华为·harmonyos
L、2185 小时前
Flutter 与开源鸿蒙(OpenHarmony):跨平台开发的新未来
flutter·华为·开源·harmonyos
L、2185 小时前
Flutter 与 OpenHarmony 深度融合实践:打造跨生态高性能应用(进阶篇)
javascript·flutter·华为·智能手机·harmonyos
威哥爱编程5 小时前
【鸿蒙开发案例篇】火力全开:鸿蒙6.0游戏开发战术手册
harmonyos·arkts·arkui