👋 你好,欢迎来到我的博客!我是【菜鸟学鸿蒙】
   我是一名在路上的移动端开发者,正从传统“小码农”转向鸿蒙原生开发的进阶之旅。为了把学习过的知识沉淀下来,也为了和更多同路人互相启发,我决定把探索 HarmonyOS 的过程都记录在这里。
  
  🛠️ 主要方向:ArkTS 语言基础、HarmonyOS 原生应用(Stage 模型、UIAbility/ServiceAbility)、分布式能力与软总线、元服务/卡片、应用签名与上架、性能与内存优化、项目实战,以及 Android → 鸿蒙的迁移踩坑与复盘。
  🧭 内容节奏:从基础到实战——小示例拆解框架认知、专项优化手记、实战项目拆包、面试题思考与复盘,让每篇都有可落地的代码与方法论。
  💡 我相信:写作是把知识内化的过程,分享是让生态更繁荣的方式。
  
   如果你也想拥抱鸿蒙、热爱成长,欢迎关注我,一起交流进步!🚀

0)先问你一句(不问我憋得难受😅)

你现在的项目是偏 HarmonyOS(华为开发者文档体系) 还是偏 OpenHarmony(开源 docs/Gitee/GitCode 体系)
两套概念基本一致,但API 包名、示例组织、文档表述会有细微差别——我下面会尽量写成“通用口径”,你对号入座就行。

1)Stage Model 的设计背景:它不是“新姿势”,而是“新边界”😎

FA(Feature Ability)那套老模型,你可以理解为:

  • 能跑、能做事、也确实养活过很多项目
  • 但随着业务复杂度上来,会出现一个经典现象:“上下文到处找、生命周期到处撞、页面路由像野生动物一样乱跑”(别装,你肯定见过🙃)

Stage Model 的核心变化,其实就一句话:

把应用组织形态从“以 Ability 为中心”调整为“以 Stage(舞台容器)承载 UIAbility,围绕 WindowStage 管 UI,路由栈自动化”。 (华为开发者)

为什么要这么干?我用“人话”给你拆三点:

  1. 模块化更清晰:AbilityStage 负责模块级初始化,UIAbility 负责可交互 UI;责任边界更像“正经工程”。(你以后找 bug 不用靠算命🔮)
  2. UI 生命周期更贴近窗口:UIAbility 生命周期与 WindowStage 创建/销毁强关联,UI 的“出生—上台—下台—退场”更好管理。 (华为开发者)
  3. 页面栈机制更统一:页面跳转走 Router,pushUrl / replaceUrl / back 等形成稳定的栈语义(你不用自己手搓一套“返回逻辑炼丹术”)。 (博客园)

2)UIAbility 生命周期:别在回调里“塞满宇宙”,系统会记仇🥲

官方文档把 UIAbility 的关键回调列得很明确:

  • 启动到前台:onCreate → onWindowStageCreate → onForeground
  • 切后台:onBackground
  • 再回前台:onNewWant → onForeground
  • 销毁窗口相关:onWindowStageWillDestroy / onWindowStageDestroy,最后 onDestroy (华为开发者)

而且还有一句很“扎心但真实”的提醒:

生命周期回调在主线程执行,别在里面搞耗时操作(否则卡顿你背锅)。 (华为开发者)

2.1 一段“能直接用”的 UIAbility 生命周期骨架(带日志 + 正确放置 loadContent)

// EntryAbility.ets
import { AbilityConstant, UIAbility, Want, window } from '@kit.AbilityKit'
import { hilog } from '@kit.PerformanceAnalysisKit'

const TAG = 'StageDeepDive'

export default class EntryAbility extends UIAbility {
  private windowStage?: window.WindowStage

  onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
    hilog.info(0x0000, TAG, `onCreate: ${JSON.stringify(want.parameters ?? {})}`)
    // ✅ 只做一次性的轻量初始化:配置、轻量缓存、DI 容器等
  }

  onWindowStageCreate(windowStage: window.WindowStage): void {
    hilog.info(0x0000, TAG, 'onWindowStageCreate')
    this.windowStage = windowStage

    // ✅ 在这里加载首页 UI(官方推荐的“上台口”)
    windowStage.loadContent('pages/Index', (err) => {
      if (err) {
        hilog.error(0x0000, TAG, `loadContent failed: ${JSON.stringify(err)}`)
        return
      }
      hilog.info(0x0000, TAG, 'loadContent success')
    })

    // ✅ 需要的话订阅 WindowStage 事件(获焦/失焦等)
    // 具体事件名以你 SDK 对应窗口开发指导为准
    // windowStage.on('windowStageEvent', (data) => { ... })
  }

  onForeground(): void {
    hilog.info(0x0000, TAG, 'onForeground')
    // ✅ 适合:恢复资源、刷新轻量数据、恢复监听
  }

  onBackground(): void {
    hilog.info(0x0000, TAG, 'onBackground')
    // ✅ 适合:保存状态、释放非必要资源、暂停动画/监听
  }

  onNewWant(want: Want): void {
    hilog.info(0x0000, TAG, `onNewWant: ${JSON.stringify(want.parameters ?? {})}`)
    // ✅ 适合:处理新的跳转意图,比如深链、通知点击
  }

  onWindowStageDestroy(): void {
    hilog.info(0x0000, TAG, 'onWindowStageDestroy')
    this.windowStage = undefined
    // ✅ 释放 UI 相关资源
  }

  onDestroy(): void {
    hilog.info(0x0000, TAG, 'onDestroy')
    // ✅ 最终释放:线程、连接、全局资源
  }
}

你注意到没:loadContent 就老老实实放 onWindowStageCreate。这点在不少说明里反复强调(WindowStage 创建完才有舞台给你上戏)。 (华为开发者)

3)WindowStage 与页面栈:一个是“舞台”,一个是“剧情推进器”🎭

3.1 WindowStage:负责把“哪个页面”端上来

OpenHarmony 的窗口开发文档明确提到:你可以通过接口获取主窗口、设置窗口属性,并通过 loadContent 为主窗口加载目标页面。 (GitCode)

我把它翻译成人话就是:

  • WindowStage = 你这场演出的舞台
  • loadContent = 你决定“开场第一幕演什么”

真实项目里,通常在 onWindowStageCreate 中把 windowStage 存起来,后续如果需要做窗口级操作(亮度/可触/沉浸等),你心里就有底。(GitCode)

3.2 页面栈:Router 帮你“自动管栈”,别再手写返回逻辑了🙏

Router 的栈语义非常直观:

  • pushUrl():压栈,保留当前页
  • replaceUrl():替换栈顶(当前页会被替换/销毁语义)
  • back():出栈回退
    并且页面栈容量有上限,超了可以 clear()(具体上限与行为以你 SDK 为准,但“栈管理”这套思路是稳定的)。 (博客园)
3.2.1 页面跳转 + 传参 + 接参(最常用三件套)
// A 页面:跳转并传参
import router from '@ohos.router'

function goDetail(id: string) {
  router.pushUrl({
    url: 'pages/Detail',
    params: { id }
  })
}
// Detail 页面:接参
import router from '@ohos.router'

@Entry
@Component
struct Detail {
  private id: string = ''

  aboutToAppear(): void {
    const params = router.getParams() as Record<string, any>
    this.id = String(params?.id ?? '')
  }

  build() {
    Column() {
      Text(`Detail id = ${this.id}`)
      Button('返回').onClick(() => router.back())
    }
  }
}

push/replace/back 以及 params/getParams 这类用法在社区与教程中被反复验证,是 Stage 里最“省心”的页面栈使用方式之一。 (博客园)

4)迁移 FA → Stage:最容易翻车的不是代码,是“习惯”😤

我见过很多迁移失败案例,核心原因就一个:
人还活在 FA 的世界里,手却在写 Stage。

下面这份清单,算是我踩坑踩出来的“止血包”:

4.1 生命周期认知要换:PageAbility/FeatureAbility 的那套别硬套

Stage 下你要把“入口逻辑”分层想清楚:

  • 模块级初始化:AbilityStage(你可以做资源预加载、线程池、模块内服务注册)
  • UI 入口与窗口:UIAbility + WindowStage(loadContent 在这里落地) (华为开发者)

4.2 上下文获取方式要换:别再到处找 featureAbility

在 Stage 里更推荐从组件/Ability 的 context 获取(而不是 FA 模式那套旧接口思维),否则耦合会越来越重。很多迁移文章也会把这一点当成“必须改”。 (腾讯云)

4.3 路由迁移要换:FA 的页面跳转思路迁到 Router 栈语义

  • 原来很多 FA 项目会“自己维护一个页面状态机”
  • 迁移后建议尽量收敛到 router.pushUrl/replaceUrl/back 的栈模型
    这样你未来做“多步流程/返回恢复”会更自然。 (博客园)

4.4 多实例/指定实例:别把“打开同一文档多窗口”写成灾难

如果你有“同一 UIAbility 需要按不同 key 管不同实例”的需求(比如文档、会话、多任务),Stage 支持通过 AbilityStage 的 onAcceptWant 进行指定实例 key 的匹配思路:如果 key 命中已存在实例,就拉回旧实例,不重新创建,并触发 onNewWant 而不是 onCreate/onWindowStageCreate。 (CSDN博客)

给你一个“能看懂逻辑”的示意(重点看 key 怎么回):

// MyAbilityStage.ets(示意思路)
import { AbilityStage, Want } from '@kit.AbilityKit'

export default class MyAbilityStage extends AbilityStage {
  onAcceptWant(want: Want): string {
    // 你可以用文件路径/会话ID当 key,让同 key 的实例复用
    const key = String(want.parameters?.instanceKey ?? '')
    return key ? `DocInstance_${key}` : ''
  }
}

4.5 loadContent 传参别硬怼:页面参数优先走 Router

很多人迁移时会纠结:
“我在 onWindowStageCreate 里 loadContent,怎么给首页传参数?”
我的建议是:

  • 首页参数:优先用 AppStorage/LocalStorage 或全局状态容器(更像工程化)
  • 页面间参数:优先用 router params
    不要把 WindowStage.loadContent 搞成“万能传参通道”,否则后期维护会很痛😵‍💫(你会发现数据从哪来完全不可追踪)

结尾:Stage Model 真不是“更麻烦”,它是“更像工程”🙂

如果你把 Stage 当“换皮 FA”,你会觉得它处处不顺手;
但如果你承认它的边界设计——

  • UIAbility 管生命周期 (华为开发者)
  • WindowStage 管窗口与首屏装载 (GitCode)
  • Router 管页面栈 (博客园)
    那你会突然发现:
    维护成本下降得非常明显,尤其是项目变大之后。

📝 写在最后

如果你觉得这篇文章对你有帮助,或者有任何想法、建议,欢迎在评论区留言交流!你的每一个点赞 👍、收藏 ⭐、关注 ❤️,都是我持续更新的最大动力!

我是一个在代码世界里不断摸索的小码农,愿我们都能在成长的路上越走越远,越学越强!

感谢你的阅读,我们下篇文章再见~👋

✍️ 作者:某个被流“治愈”过的 移动端 老兵
📅 日期:2025-11-05
🧵 本文原创,转载请注明出处。

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐