理解 Stage 模型 —— HarmonyOS 应用架构新标准

理解 Stage 模型 —— HarmonyOS 应用架构新标准
在这里插入图片描述


个人主页:ujainu

文章目录

引言:为什么必须掌握 Stage 模型?

HarmonyOS 3.1 起,华为正式引入 Stage 模型,并宣布 FA(Feature Ability)模型逐步废弃。到 HarmonyOS 6.0.0(API 6.0.2) 时代,Stage 模型已成为唯一推荐的应用架构标准

如果你仍在使用 FA 模型,你的应用将:

  • ❌ 无法上架新版华为应用市场;
  • ❌ 无法使用最新 UI 能力(如 Canvas 高性能绘制、分布式窗口);
  • ❌ 失去对多设备协同、后台任务管理等高级特性的支持。

本文将带你从零彻底搞懂 Stage 模型,涵盖:

  • ✅ Stage vs FA 模型核心差异;
  • UIAbilityWindowStageContext 三大核心概念;
  • ✅ 项目结构文件(main_pages.json, module.json5)详解;
  • ✅ 如何获取屏幕尺寸、窗口、能力上下文;
  • ✅ 完整可运行代码示例(适配 API 6.0.2)。

所有内容均基于 DevEco Studio 4.1 + HarmonyOS 6.0.0 模拟器 实测验证。


一、Stage 模型 vs FA 模型:架构演进之路

1. FA 模型(已废弃)

FA(Feature Ability)模型是 HarmonyOS 早期采用的架构,灵感来自 Android 的 Activity/Service 模式。

// FA 模型示例(已不推荐)exportdefaultclassMainAbilityextendsAbility{onCreate(){// 初始化逻辑}}
FA 模型缺陷:能力(Ability)与 UI 强耦合;多窗口、多实例管理复杂;缺乏统一的生命周期管理;难以支持跨设备协同。

2. Stage 模型(现代标准)

Stage 模型采用 “能力(Ability) + 窗口(Window) + 页面(Page)”三层解耦架构,更符合现代操作系统设计理念。

维度FA 模型Stage 模型
入口MainAbilityUIAbility
UI 管理Ability 直接控制 UIWindowStage 管理窗口,Page 描述 UI
生命周期分散在 Ability 中统一由 UIAbilityWindowStage 协同管理
多实例支持困难原生支持(如分屏、悬浮窗)
跨设备协同需手动实现内置 Continuation 能力
💡 核心思想
UI 与业务逻辑分离,窗口与页面解耦,能力可复用

二、Stage 模型三大核心概念

1. UIAbility:应用的能力入口

UIAbility 是 Stage 模型中承载 UI 的能力单元,相当于 FA 模型中的 MainAbility,但职责更清晰。

// src/main/ets/UIAbility.tsimport UIAbility from'@ohos.app.ability.UIAbility';exportdefaultclassEntryAbilityextendsUIAbility{onCreate(want, launchParam){console.log('UIAbility created');}onWindowStageCreate(windowStage){// 关键:在此加载主页面 windowStage.loadContent('pages/Index',(err, data)=>{if(err.code){console.error('Failed to load content: '+JSON.stringify(err));return;}console.log('Content loaded successfully');});}onDestroy(){console.log('UIAbility destroyed');}}
代码逐行解析onCreate():Ability 创建时调用(适合初始化全局状态);onWindowStageCreate(windowStage)窗口创建完成,此时可加载页面;windowStage.loadContent('pages/Index'):指定主页面路径(相对于 src/main/ets);onDestroy():Ability 销毁前清理资源。
📌 关键点
UI 不再在 Ability 中定义,而是在独立的 Page 文件中描述(如 Index.ets)。

2. WindowStage:窗口管理中枢

WindowStage 代表一个应用窗口实例,负责:

  • 加载页面内容;
  • 管理窗口属性(大小、透明度、焦点);
  • 处理窗口生命周期事件。
// 在 UIAbility 中获取 WindowStageonWindowStageCreate(windowStage: window.WindowStage){// 获取窗口对象const window = windowStage.getMainWindowSync();// 设置窗口背景色 window.setWindowBackgroundColor('#FFFFFF');// 加载页面 windowStage.loadContent('pages/Index', callback);}
典型应用场景:全屏游戏:window.setFullScreen(true)悬浮窗:通过 windowManager 创建新 WindowStage多窗口协同:一个 Ability 可管理多个 WindowStage

3. Context:上下文获取桥梁

Context 是访问系统服务、资源、能力的统一入口。在 ArkTS 中,通过 getContext(this) 获取。

// 在 Page 组件中获取 Context@Entry@Component struct MyPage {build(){Column(){Button("获取屏幕信息").onClick(()=>{const context =getContext(this);const config = context.config;// 屏幕配置const ability = context.getUIAbility();// 获取 UIAbility 实例console.log(`Screen: ${config?.screenWidth} x ${config?.screenHeight}`);})}}}
关键 APIgetContext(this):在 @Component 中获取上下文;context.config:获取设备配置(屏幕宽高、DPI、语言等);context.getUIAbility():获取当前 UIAbility 实例;context.resourceManager:访问字符串、图片等资源。
⚠️ 注意
getContext(this) 中的 this 必须是 @Component 装饰的 struct 实例,否则会报错。

三、项目结构文件详解(Stage 模型专属)

Stage 模型引入了新的配置文件体系,取代 FA 模型的 config.json

1. main_pages.json:页面路由清单

路径src/main/resources/base/profile/main_pages.json
{"src":["pages/Index","pages/Detail"]}
作用:声明所有可被 loadContent() 加载的页面路径;路径相对于 src/main/ets必须显式注册,否则 loadContent 会失败。
💡 最佳实践:主页面放第一个;按功能模块组织路径(如 pages/game/Level1)。

2. module.json5:模块级配置(核心!)

路径src/main/module.json5
{ "module": { "name": "entry", "type": "entry", "description": "$string:module_desc", "mainElement": "EntryAbility", // 对应 UIAbility 类名 "deviceTypes": [ "phone", "tablet" ], "deliveryWithInstall": true, "installationFree": false, "pages": "$profile:main_pages", // 引用 main_pages.json "abilities": [ { "name": "EntryAbility", "srcEntry": "./ets/UIAbility.ts", // Ability 入口文件 "description": "$string:EntryAbility_desc", "icon": "$media:icon", "label": "$string:EntryAbility_label", "startWindowIcon": "$media:icon", "startWindowBackground": "$color:start_window_background", "exported": true, "skills": [ { "entities": ["entity.system.home"], "actions": ["action.system.home"] } ] } ] } } 
关键字段解析
📌 重要变化
FA 模型的 config.json 已被 module.json5 + main_pages.json 取代,配置更模块化、可读性更强

3. build-profile.json5:构建配置

路径:项目根目录 /build-profile.json5
{ "app": { "signingConfigs": [], "products": [ { "name": "default", "signingConfig": "default", "compatibleSdkVersion": "6.0.2(22)", // 关键:指定 API 版本 "runtimeOnly": false } ] } } 
作用:指定兼容的 SDK 版本(compatibleSdkVersion);配置签名、产品变体;控制是否仅运行时(runtimeOnly)。
适配提示
你的虚拟机为 API 6.0.2(22),此处必须匹配,否则安装失败。

四、实战:获取屏幕尺寸、窗口、能力上下文

场景:在页面中动态获取屏幕宽高并调整 UI

// 导入正确的模块和类型(适配 API 6.0.2)import window from'@ohos.window';import common from'@ohos.app.ability.common';@Entry@Component struct ScreenInfoPage {@State screenWidth:number=0;@State screenHeight:number=0;@State windowMode:string='API 6 不支持获取';aboutToAppear():void{// 延迟执行,确保窗口已创建setTimeout(()=>{this.updateScreenInfo();},300);}updateScreenInfo():void{try{// 1. 获取并转换 Context 类型const context =getContext(this)as common.UIAbilityContext;if(!context){console.error('获取 Context 失败');return;}// 2. 通过 windowStage 获取主窗口尺寸(API 6 兼容方式)const windowStage = context.windowStage;if(windowStage){const mainWindow = windowStage.getMainWindowSync();const windowProperties = mainWindow.getWindowProperties();this.screenWidth = windowProperties.windowRect.width;this.screenHeight = windowProperties.windowRect.height;}// 3. 打印 Ability 信息if(context.abilityInfo){console.log('UIAbility name:', context.abilityInfo.name);}// 4. 窗口模式获取在 API 6 中不可用,直接设置提示this.windowMode ='API 6 不支持获取';}catch(e){console.error('更新屏幕信息失败:',JSON.stringify(e));}}build(){Column(){Column(){Text(`屏幕尺寸:${this.screenWidth} x ${this.screenHeight}`).fontSize(18)Text(`窗口模式:${this.windowMode}`).fontSize(16).margin({ top:10})Button("刷新信息").onClick(()=>this.updateScreenInfo()).margin({ top:20})}.justifyContent(FlexAlign.Center)}.width('100%').height('100%').backgroundColor('#f0f0f0')}}
在这里插入图片描述
代码深度解析getContext(this):在 @Component 中安全获取上下文;context.config:直接读取屏幕宽高(单位:px),无需异步context.getUIAbility():获取 UIAbility 实例,用于访问生命周期或窗口;currentWindowStage.getMainWindowSync():同步获取主窗口(Stage 模型特有);getWindowMode():判断当前窗口模式(全屏/悬浮等)。
优势
所有操作均为同步调用,无回调地狱,代码简洁可靠。

五、常见问题与最佳实践

❓ Q1:如何在非 UIAbility 中获取 Context?

A:通过 Ability 的 context 属性传递,或使用 ApplicationContext(需权限)。

❓ Q2:main_pages.json 能否动态修改?

A:不能。所有页面必须在编译时注册,这是出于安全与性能考虑。

✅ 最佳实践:

  • Ability 职责单一:一个 UIAbility 只负责一类功能(如主界面、设置页);
  • 避免在 Page 中持有 Ability 引用:通过事件通信,而非直接调用;
  • 窗口操作放 Ability 中:Page 只负责 UI 描述,窗口管理归 UIAbility

六、总结:Stage 模型的核心价值

维度价值
架构清晰Ability(能力) + Window(窗口) + Page(页面)三层解耦
生命周期可控统一入口,便于资源管理与内存优化
多设备友好原生支持手机、平板、车机、手表的窗口适配
未来-proof华为官方唯一维护的模型,持续获得新特性
🚀 行动建议:新项目必须使用 Stage 模型;老 FA 项目尽快迁移(华为提供迁移工具);深入理解 UIAbilityWindowStage 的协作机制。

Read more

HAL库软件IIC驱动AT24C02/AT24C32:从时序解析到多模式读写实战

1. 为什么需要软件IIC?从硬件IIC的痛点说起 刚开始接触STM32的IIC通信时,我和很多初学者一样,首先尝试的是硬件IIC。毕竟STM32提供了专门的I2C外设,用起来应该很方便才对。但实际使用中,我发现硬件IIC并没有想象中那么美好。 硬件IIC最大的问题在于时序的严格性。STM32的硬件IIC对时序要求非常苛刻,稍微有点干扰或者时序不匹配就容易出现卡死、无响应的情况。特别是在多设备共享总线时,一旦某个设备没有及时响应,整个总线就可能陷入死锁状态,需要重新初始化才能恢复。 相比之下,软件IIC虽然占用CPU资源,但有着无可替代的优势。首先是灵活性,你可以完全控制时序的每个细节,根据不同的从设备调整延时时间。其次是稳定性,不会出现硬件IIC那种莫名其妙的死锁问题。最重要的是,软件IIC能让你真正理解IIC协议的本质,而不是简单地调用库函数。 我在实际项目中选择软件IIC还有一个重要原因:引脚分配的灵活性。硬件IIC的引脚是固定的,当这些引脚被其他功能占用时,软件IIC可以任意选择可用的GPIO引脚,这在PCB布局时提供了很大的便利。 2. 深入理解IIC时序:从信号

By Ne0inhk
Java LLM开发框架全面解析:从Spring AI到Agents-Flex

Java LLM开发框架全面解析:从Spring AI到Agents-Flex

🧑 博主简介:ZEEKLOG博客专家,历代文学网(PC端可以访问:https://literature.sinhy.com/#/?__c=1000,移动端可关注公众号 “ 心海云图 ” 微信小程序搜索“历代文学”)总架构师,16年工作经验,精通Java编程,高并发设计,分布式系统架构设计,Springboot和微服务,熟悉Linux,ESXI虚拟化以及云原生Docker和K8s,热衷于探索科技的边界,并将理论知识转化为实际应用。保持对新技术的好奇心,乐于分享所学,希望通过我的实践经历和见解,启发他人的创新思维。在这里,我希望能与志同道合的朋友交流探讨,共同进步,一起在技术的世界里不断学习成长。 🤝商务合作:请搜索或扫码关注微信公众号 “ 心海云图 ” Java LLM开发框架全面解析:从Spring AI到Agents-Flex 在人工智能席卷全球的今天,Java开发者无需转向Python生态,也能充分利用大语言模型的强大能力,这得益于日益成熟的Java LLM开发框架。 近年来,随着大语言模型(LLM)技术的迅猛发展,AI能力已成为现代应用开发不可或缺的部分。作为企业

By Ne0inhk

能刷java题的网站

以下是一些适合刷Java题的优质网站,涵盖从基础到进阶、算法面试及实战项目等多种需求: 一、综合编程练习平台 1. LeetCode (leetcode.com) * 特点 :全球最知名的算法题库,含海量Java题目,分类清晰(Easy/medium/hard),适合求职面试准备。 * 优势 :社区讨论活跃,高频题目更新,提供详细解题报告和讨论区。 * 语言支持 :支持Java及其他主流语言,免费账号可解锁部分题目,付费会员解锁全部。 2. HackerRank (hackerrank.com) * 特点 :覆盖多种编程领域(数据结构、算法、数据库等),Java专区题目丰富,含实战项目(如API开发)。 * 优势 :免费使用,提供代码评测和可视化学习路径,适合系统性学习。 * 场景 :企业招聘常参考,适合检验综合编码能力。 3. CodeSignal (codesignal.com) * 特点 :实时编码测试平台,

By Ne0inhk
JDK21安装与配置教程

JDK21安装与配置教程

文章目录 * 一、下载JDK * 1. 下载地址 * 2. 下载JDK21 * 二、JDK21安装及配置 * 1. 解压zip压缩包 * 2. 配置Java环境变量 * 2.1 打开系统属性设置 * 2.2 新建系统环境变量 * 2.3 编辑 PATH 环境变量 * 2.4 验证环境变量是否配置成功 一、下载JDK 1. 下载地址 华为云镜像下载地址: 地址 1(OracleJDK):https://repo.huaweicloud.com/java/jdk/ 地址 2(OpenJDK):https://mirrors.huaweicloud.com/openjdk/ 地址

By Ne0inhk