了解鸿蒙开发（一）-- 运行时角度

前言

希望通过学习鸿蒙开发达成一下几个目的：

借助全中文文档，更快地构建原生开发所需的整体概念和知识体系，并以点破面，完成原生开发技能树的拓展。

为可能到来的新赛道，做好知识储备，静待风起。

本篇以 Web 前端工程师的认知，从应用运行的角度，去理解鸿蒙开发在开发什么。

应用模型 - 鸿蒙应用的基本法则

应用模型是 HarmonyOS 为开发者提供的应用程序所需能力的抽象提炼，它提供了应用程序必备的组件和运行机制 -- HarmonyOS Developer 文档

应用模型定义了鸿蒙应用开发的 “玩法规则”。开发鸿蒙应用就是在既定的运行时机制下，使用组件实现应用功能。

具体地，应用模型包含应用组件、应用进程模型、应用线程模型、应用任务管理模型、应用配置文件五个要素。（后四个都是运行机制）

在 HarmonyOS 的迭代过程中，有 FA 和 Stage 两种模型，他们在五个要素中都有不同点，我们这里主要认识日后主推的 Stage 应用模型。

Stage 模型开发概述

应用组件

应用组件，是开发者主要使用和实现的实体。在 Stage 应用模型中，应用组件分为 UIAbility 和 ExtentionAbility。

UIAbility 是包含 UI 界面的应用组件，是前端开发熟悉的页面的载体，主要用于和用户交互。UIAbility 像是 Chrome 中的一个展示多页应用的标签，具体的 UI 界面是由多个页面完成。

ExtentionAbility 则是针对某一应用场景的应用组件，不一定包含 UI 界面。比如输入法场景、桌面卡片 / 小组件场景、后台服务等。具体的组件类型可以查阅文档得知。

其他核心概念

在应用组件和进程、线程等运行机制中间，还有一层实现和概念，把组件和运行机制串联了起来。可以从文档中的这张图来理解。

AbilityStage 和 Context

应用组件是无法自驱的，必然需要一个人来驱动和协调 Ability，这个 “人” 就是 AbilityStage。当应用启动时，它会首先被创建，进而开始加载执行默认的 Ability。

与 AbilityStage 一同创建的还有 Context，记录了该 AbilityStage 的所有上下文信息，每个 UIAbility 都会从这里派生出自己的上下文（UIAbilityContext）。UIAbility 中的页面可以通过上下文来获取一些运行信息和方法。

WindowStage 和 Page

每个 UIAbility 在运行时并不直接管理页面，而是通过持有的 WindowStage 来管理页面。这是因为在现在的应用中，不仅仅只有单个全屏窗口的形态了。比如文档应用可以有多个窗口用于实时预览，视频应用可以实现悬浮窗口一直播放视频等。与在页面中模拟出来的窗口相比，它有更准确的生命周期和更强的交互能力。（因为更贴近应用模型的底层实现）

终于到了前端开发熟悉的页面（Page）了。页面是使用 ArkUI 来实现的交互界面，也就是用户看到的画面。一个 UIAbility 里可以有多个页面，展示在指定的窗口里。

这里值得一提的是，在鸿蒙开发中，除了 ArkUI ，也还有类 Web 开发范式，即用 html、css、js 构建页面 UI（ArkUI 仅使用 ArkTS 构建页面，没有 html 和 css）。** 但在 Stage 开发模型中，只能使用 ArkUI 进行页面开发。** 所以对个人来说，遵循 Stage 应用模型，使用 ArkTS 和 ArkUI 实现鸿蒙应用是更符合鸿蒙发展趋势，会有长期收益的。对公司来说，是选择 Stage 模型完全复刻现有应用，还是选择 FA 应用模型，使用类 Web 开发范式快速迁移已现有的 Web 页面。要结合外部因素，如华为的决心和投入、政策的导向等，和内部因素，如当前的技术选型、可以调度的资源等去通盘考虑决定。

认识 UIAbility

通过对 Stage 开发模型核心概念的学习，我们可以知道，用户看到的鸿蒙应用，是以 AbilityStage 为基础，以 UIAbility 为主要调度单元的一个能力集合。

进一步认识 UIAbility，了解 UIAbility 的能力范围， 可以帮助我们更好地拆分应用能力，设计应用结构。

下面，我们由内（生命周期）到外（与其他个体的交互）的认识 UIAbility。

生命周期

在保留模式（retained mode）的 GUI 世界中，这里的 “万事万物” 和人一样是有 “生老病死” 的周期性，我们通过响应周期节点的回调函数，构建、改变 UI 状态，进而描绘某一时期时的界面视图。UIAbility 作为 “世界” 中的一员，自然有它的生命周期。

从图中可以看到，UIAbility 的生命周期是用户使用视角下的，包含创建、来到前台、进入后台、销毁四个节点。因为它和 WindowStage “同生共死”，所以它们的生命周期也是关联的。把这张图大致印在心里后，我们在实际开发时，也就可以做到有的放矢。

在这些节点中，我们可以感知到 UIAbility 的当前状态（已创建、已可见、当前聚焦），也可以通过一些手段，与它的相关实体进行交互，进而改变应用状态。

与页面交互

我们可以通过事件机制向 UIAbility 内的页面发送事件，通知它做某些改变，通过全局对象和页面共享数据。具体的使用方法还是详见文档。需要说明的是，事件仅限 UIAbility 内部，因为 EventBus 是挂载在 UIAbility 自己的 Context 上，一个页面是获取不到其他 UIAbility 的 Context 的。全局对象则是看应用模型的，在 Stage 中，因为所有 Ability 都是共享同一个 ArkTS 引擎，所以也就只有一个全局对象，任何人都可以在这个对象上进行读写，是有覆盖风险的。（FA 模型中，Ability 会有自己的 ArkTS 引擎，因此全局对象是独立的）

与其他 Ability 交互

与其他 Ability 的交互，可以总结为两样东西：打开方法和信息载体。目前看，与其他 Ability 的交互就是打开唤起其他的 Ability，根据是否需要在它关闭时获取一些结果，方法会有细分。信息载体 —— want，则是描述了要以何种方式打开哪个 Ability，通过确定一些参数，我们可以打开同应用内的 Ability，打开不同应用的 Ability ，以便实现现在常见的三方支付等场景。这里说的 “何种方式”，是指的 “新建” 还是 “复用”。

这里补充一下 UIAbility 的启动模式，有三种：单例模式、标准模式和指定模式。单例模式就是如果当前 Ability 已经被创建了，就只是把它换到前台，不再新建。标准模式是每次都会新建。在一些复杂场景下，则是在调用时决定时新建还是复用，即指定模式，是需要在 Want 中指明的。具体的操作方式详见文档

了解进程和线程模型

进程和线程在文档中的描述相对较少。需要了解的是，同一个应用的所有 Ability 都是运行在同一个进程中，webview 则是有自己的渲染进程。一个进程中会有一个主线程，和若干 worker 线程，线程中都会有 ArkTS 引擎。如上文所说，在 Stage 模型下，UIAbility 都是运行在主线程的 ArkTS 引擎中。主线程的功能点大致如下，文档中有提到：

执行 UI 绘制；

管理主线程的 ArkTS 引擎实例，使多个 UIAbility 组件能够运行在其之上；

管理其他线程（例如 Worker 线程）的 ArkTS 引擎实例，例如启动和终止其他线程；

分发交互事件；

处理应用代码的回调，包括事件处理和生命周期管理；

接收 Worker 线程发送的消息；

限于我自己的知识短板，对这一块的理解难以深刻，待后续有实际应用时，再进行研究。

后记

通过对鸿蒙文档应用模型章节的阅读，大概建立起了鸿蒙应用运行时的样子：在一个进程的主线程中，通过 AbilityStage 调度不同的 UIAbility，进一步地，UIAbility 自己管理窗口、展示页面。

另外，对一个现有的复杂 App 来说，选择何种开发模型，是需要考量的。由于 Stage 模型和 FA 模型不能混用，即一个应用中，不可能一个模块是用 Stage 模型开发，一个模块是 FA 模型开发。所以应用主体的选择，会限制分模块能不能使用类 Web 开发范式，快速迁移已有 Web 、小程序页面的。

下一篇大概会从编译时的角度，去了解鸿蒙应用具体的代码是怎么组织的，模块如何复用、最终打包产物是怎样的，进而建立起完整的鸿蒙应用开发体系。