希望通过学习鸿蒙开发达成一下几个目的:
本篇以 Web 前端工程师的认知,从应用运行的角度,去理解鸿蒙开发在开发什么。
应用模型是HarmonyOS为开发者提供的应用程序所需能力的抽象提炼,它提供了应用程序必备的组件和运行机制 -- HarmonyOS Developer 文档
应用模型定义了鸿蒙应用开发的“玩法规则”。开发鸿蒙应用就是在既定的运行时机制下,使用组件实现应用功能。
具体地,应用模型包含应用组件、应用进程模型、应用线程模型、应用任务管理模型、应用配置文件五个要素。(后四个都是运行机制)
在 HarmonyOS 的迭代过程中,有 FA 和 Stage 两种模型,他们在五个要素中都有不同点,我们这里主要认识日后主推的 Stage 应用模型。
应用组件,是开发者主要使用和实现的实体。在 Stage 应用模型中,应用组件分为 UIAbility 和 ExtentionAbility。
UIAbility 是包含 UI 界面的应用组件,是前端开发熟悉的页面的载体,主要用于和用户交互。UIAbility 像是 Chrome 中的一个展示多页应用的标签,具体的 UI 界面是由多个页面完成。
ExtentionAbility 则是针对某一应用场景的应用组件,不一定包含 UI 界面。比如输入法场景、桌面卡片/小组件场景、后台服务等。具体的组件类型可以查阅文档得知。
在应用组件和进程、线程等运行机制中间,还有一层实现和概念,把组件和运行机制串联了起来。可以从文档中的这张图来理解。
应用组件是无法自驱的,必然需要一个人来驱动和协调 Ability,这个“人”就是 AbilityStage。当应用启动时,它会首先被创建,进而开始加载执行默认的 Ability。
与 AbilityStage 一同创建的还有 Context,记录了该 AbilityStage 的所有上下文信息,每个 UIAbility 都会从这里派生出自己的上下文(UIAbilityContext)。UIAbility 中的页面可以通过上下文来获取一些运行信息和方法。
每个 UIAbility 在运行时并不直接管理页面,而是通过持有的 WindowStage 来管理页面。这是因为在现在的应用中,不仅仅只有单个全屏窗口的形态了。比如文档应用可以有多个窗口用于实时预览,视频应用可以实现悬浮窗口一直播放视频等。与在页面中模拟出来的窗口相比,它有更准确的生命周期和更强的交互能力。(因为更贴近应用模型的底层实现)
终于到了前端开发熟悉的页面(Page)了。页面是使用 ArkUI 来实现的交互界面,也就是用户看到的画面。一个 UIAbility 里可以有多个页面,展示在指定的窗口里。
这里值得一提的是,在鸿蒙开发中,除了 ArkUI ,也还有类 Web 开发范式,即用 html、css、js 构建页面 UI(ArkUI 仅使用 ArkTS 构建页面,没有 html 和 css)。** 但在 Stage 开发模型中,只能使用 ArkUI 进行页面开发。** 所以对个人来说,遵循 Stage 应用模型,使用 ArkTS 和 ArkUI 实现鸿蒙应用是更符合鸿蒙发展趋势,会有长期收益的。对公司来说,是选择 Stage 模型完全复刻现有应用,还是选择FA 应用模型,使用类 Web 开发范式快速迁移已现有的 Web 页面。要结合外部因素,如华为的决心和投入、政策的导向等,和内部因素,如当前的技术选型、可以调度的资源等去通盘考虑决定。
通过对 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,根据是否需要在它关闭时获取一些结果,方法会有细分。信息载体 —— want,则是描述了要以何种方式打开哪个 Ability,通过确定一些参数,我们可以打开同应用内的 Ability,打开不同应用的 Ability ,以便实现现在常见的三方支付等场景。这里说的“何种方式”,是指的“新建”还是“复用”。
这里补充一下 UIAbility 的启动模式,有三种:单例模式、标准模式和指定模式。单例模式就是如果当前 Ability 已经被创建了,就只是把它换到前台,不再新建。标准模式是每次都会新建。在一些复杂场景下,则是在调用时决定时新建还是复用,即指定模式,是需要在 Want 中指明的。具体的操作方式详见文档
进程和线程在文档中的描述相对较少。需要了解的是,同一个应用的所有 Ability 都是运行在同一个进程中,webview 则是有自己的渲染进程。一个进程中会有一个主线程,和若干 worker 线程,线程中都会有 ArkTS 引擎。如上文所说,在 Stage 模型下,UIAbility 都是运行在主线程的 ArkTS 引擎中。主线程的功能点大致如下,文档中有提到:
限于我自己的知识短板,对这一块的理解难以深刻,待后续有实际应用时,再进行研究。
通过对鸿蒙文档应用模型章节的阅读,大概建立起了鸿蒙应用运行时的样子:在一个进程的主线程中,通过 AbilityStage 调度不同的 UIAbility,进一步地,UIAbility 自己管理窗口、展示页面。
另外,对一个现有的复杂 App 来说,选择何种开发模型,是需要考量的。由于 Stage 模型和 FA 模型不能混用,即一个应用中,不可能一个模块是用 Stage 模型开发,一个模块是 FA 模型开发。所以应用主体的选择,会限制分模块能不能使用类 Web 开发范式,快速迁移已有 Web 、小程序页面的。
下一篇大概会从编译时的角度,去了解鸿蒙应用具体的代码是怎么组织的,模块如何复用、最终打包产物是怎样的,进而建立起完整的鸿蒙应用开发体系。