HarmonyOs应用《日记本》开发第2篇 - Stage模型

HarmonyOS 提供了两种应用模型:FA(Feature Ability)模型和 Stage 模型。从 HarmonyOS 3.1开始,Stage 模型成为官方推荐的应用开发模型。我们的日记应用正是基于 Stage 模型构建的。本篇将深入解析 Stage模型的核心概念,并通过日记项目的实际代码来理解其工作原理。

Stage 模型 vs FA 模型

核心区别

特性FA 模型Stage 模型
开发范式类 Ace 开发ArkTS 声明式
组件模型PageAbility / ServiceAbilityUIAbility / ExtensionAbility
配置文件config.jsonmodule.json5
生命周期较简单更完善,支持多实例、多窗口
UI 开发JS/ArkTS 混合纯 ArkTS 声明式
数据共享DataAbilityDataShareExtensionAbility

为什么选择 Stage 模型

  1. 更清晰的架构:UI 与业务逻辑分离,UIAbility 专注窗口管理
  2. 更强大的生命周期:支持前后台切换、多窗口、多实例
  3. 更好的扩展性:ExtensionAbility 支持多种场景扩展
  4. 统一的配置体系:json5 格式配置,更灵活可读

Stage 模型的核心概念

1. UIAbility

UIAbility 是 Stage 模型中带有 UI 界面的组件,负责与用户交互。在我们的日记应用中:

// EntryAbility.etsimport{UIAbility,AbilityConstant,Want}from'@kit.AbilityKit';import{window}from'@kit.ArkUI';import{diaryStore}from'../utils/DiaryStore';exportdefaultclassEntryAbilityextendsUIAbility{asynconCreate(want:Want,launchParam:AbilityConstant.LaunchParam):Promise<void>{// 初始化数据存储awaitdiaryStore.init(this.context);}onWindowStageCreate(windowStage:window.WindowStage):void{windowStage.loadContent('pages/Index',(err)=>{if(err.code){console.error('Failed to load content. cause: '+JSON.stringify(err));return;}console.info('Succeeded in loading content.');});}}

2. WindowStage

WindowStage 是窗口管理器,每个 UIAbility 实例都持有一个 WindowStage,负责加载和管理 UI 内容:

onWindowStageCreate(windowStage:window.WindowStage):void{// 加载入口页面windowStage.loadContent('pages/Index',(err)=>{// 回调处理});}

3. Context

Context 是应用上下文对象,提供了访问应用资源、文件系统、偏好存储等能力。在日记项目中,Context 被传递给 DiaryStore 进行数据初始化:

asynconCreate(want:Want,launchParam:AbilityConstant.LaunchParam):Promise<void>{awaitdiaryStore.init(this.context);// this.context 即 UIAbility 的上下文}

DiaryStore 接收 Context 并初始化 Preferences:

asyncinit(context:Context):Promise<void>{this.store=awaitpreferences.getPreferences(context,{name:'diary_store'});}

UIAbility 生命周期详解

Stage 模型中 UIAbility 的生命周期比 FA 模型更加丰富:

应用启动 │ ▼ onCreate(want, launchParam) │ → 初始化数据存储 ▼ onWindowStageCreate(windowStage) │ → 加载首页 pages/Index ▼ onForeground() │ → 应用进入前台,可交互 ▼ [用户使用中...] │ ▼ onBackground() │ → 应用进入后台 ▼ onWindowStageDestroy() │ → 窗口销毁 ▼ onDestroy() │ → Ability 销毁 ▼ [进程可能被回收]

日记项目中的生命周期实现

exportdefaultclassEntryAbilityextendsUIAbility{// 1. Ability 创建时调用asynconCreate(want:Want,launchParam:AbilityConstant.LaunchParam):Promise<void>{awaitdiaryStore.init(this.context);}// 2. 新的调用(singleInstance 模式下会触发)onNewSession(want:Want,launchParam:AbilityConstant.LaunchParam):void{}// 3. 窗口创建时调用onWindowStageCreate(windowStage:window.WindowStage):void{windowStage.loadContent('pages/Index',(err)=>{if(err.code){console.error('Failed to load content. cause: '+JSON.stringify(err));return;}console.info('Succeeded in loading content.');});}// 4. 窗口销毁时调用onWindowStageDestroy():void{}// 5. 应用进入前台onForeground():void{}// 6. 应用进入后台onBackground():void{}// 7. Ability 销毁onDestroy():void{}}

生命周期中的数据初始化策略

在本项目中,数据存储的初始化放在onCreate中:

asynconCreate(want:Want,launchParam:AbilityConstant.LaunchParam):Promise<void>{awaitdiaryStore.init(this.context);}

为什么放在 onCreate?

  • onCreate是 Ability 生命周期的第一个回调
  • 此时 Context 已经可用,可以安全地初始化存储
  • onWindowStageCreate加载 UI 之前完成,确保页面加载数据时存储已就绪
  • 使用await确保异步初始化完成后再继续

Want 机制

onCreate接收的want参数包含了启动 Ability 时传递的信息:

interfaceWant{bundleName?:string;// 目标包名abilityName?:string;// 目标 Ability 名uri?:string;// URItype?:string;// MIME 类型parameters?:Record<string,Object>;// 自定义参数}

在日记应用中,want由系统在桌面图标点击时传入,携带了entity.system.homeaction.system.home信息,使应用作为桌面入口启动。

module.json5 中的 Ability 配置

Stage 模型的配置在module.json5中完成:

{ "module": { "name": "entry", "type": "entry", "description": "$string:module_desc", "mainElement": "EntryAbility", "deviceTypes": ["phone", "tablet"], "deliveryWithInstall": true, "installationFree": false, "pages": "$profile:main_pages", "abilities": [ { "name": "EntryAbility", "srcEntry": "./ets/entryability/EntryAbility.ets", "description": "$string:EntryAbility_desc", "icon": "$media:app_icon", "label": "$string:EntryAbility_label", "startWindowIcon": "$media:app_icon", "startWindowBackground": "$color:start_window_background", "exported": true, "skills": [ { "entities": ["entity.system.home"], "actions": ["action.system.home"] } ] } ] } }

关键字段解读

字段说明
mainElement模块的主入口 Ability
srcEntryAbility 源码路径
deviceTypes支持的设备类型
pages页面路由配置,指向$profile:main_pages
skills声明 Ability 可响应的意图
exported是否允许其他应用调用
startWindowIcon启动窗口图标
startWindowBackground启动窗口背景色

Stage 模型的页面加载机制

在 Stage 模型中,页面路由通过main_pages.json配置:

{"src":["pages/Index","pages/DiaryEdit","pages/DiaryDetail"]}

页面之间通过router模块进行导航:

import{router}from'@kit.ArkUI';// 跳转到编辑页router.pushUrl({url:'pages/DiaryEdit'});// 跳转到详情页并传参router.pushUrl({url:'pages/DiaryDetail',params:{id:item.id}});// 返回上一页router.back();

小结

Stage 模型是 HarmonyOS 推荐的应用开发模型,提供了更清晰的架构设计和更强大的生命周期管理。通过日记项目的EntryAbility实现,我们理解了:

  1. UIAbility 是 UI 交互的核心载体
  2. 生命周期回调各有分工,onCreate负责初始化,onWindowStageCreate负责加载 UI
  3. Context 是访问系统能力的桥梁
  4. module.json5 是 Stage 模型的核心配置文件