前言HarmonyOS鸿蒙作为华为自主研发的分布式操作系统正在以惊人的速度占领市场。本文将基于一个真实的鸿蒙原生应用「小分享」从项目架构的全景入手建立对整个工程的认知。小分享是一款支持文字、图片、链接分享的工具类应用使用了 HarmonyOS 最新的ArkTS 声明式开发范式和Stage 模型。本系列共 100 篇文章将从零到一拆解小分享 App 的实现过程涵盖组件、界面编写、状态管理、系统能力集成、性能优化、测试与发布全链路。一、HarmonyOS 开发范式演进1.1 FA 模型与 Stage 模型对比HarmonyOS 应用开发经历了两代模型演进开发者必须清楚两者的差异对比维度FA 模型旧Stage 模型新Ability 类型PageAbility / ServiceAbility / DataAbilityUIAbility / ExtensionAbility配置文件config.jsonmodule.json5开发语言Java / JavaScriptArkTS / CUI 范式基于XML / JavaScript基于ArkTS声明式生命周期复杂多状态简化清晰推荐场景历史遗留项目新项目首选1.2 Stage 模型核心组件Stage 模型主要包含以下核心组件UIAbility承载 UI 的核心组件负责窗口管理与生命周期调度ExtensionAbility扩展能力如备份、卡片、输入法等WindowStage窗口舞台承载所有 UI 内容AbilityLoaderAbility 加载器负责实例化Context上下文对象提供系统能力访问入口二、小分享 App 项目目录结构打开工程根目录xiaofenxiang_ohos_app可以看到如下典型结构xiaofenxiang_ohos_app/ ├── AppScope/ # 应用级配置 │ ├── app.json5 # 应用全局配置 │ └── resources/ # 应用级资源 ├── entry/ # 主模块 │ └── src/ │ ├── main/ │ │ ├── ets/ # ArkTS 源码 │ │ │ ├── common/ # 公共类型定义 │ │ │ ├── components/ # 自定义组件 │ │ │ ├── entryability/ # 入口 Ability │ │ │ └── pages/ # 页面 │ │ ├── module.json5 # 模块配置 │ │ └── resources/ # 模块资源 │ ├── mock/ # Mock 数据 │ └── ohosTest/ # 测试代码 ├── oh-package.json5 # 工程级依赖配置 └── build-profile.json5 # 构建配置这种「AppScope entry 多 HSP/HAR」的结构是 HarmonyOS Stage 模型下的标准工程组织方式。详细工程目录说明可参考 HarmonyOS 官方工程结构文档。三、应用级配置 AppScope/app.json53.1 完整配置文件小分享 App 的应用级配置如下{ app: { bundleName: com.shaohushuo.myapplication, vendor: example, versionCode: 1000000, versionName: 1.0.0, icon: $media:layered_image, label: $string:app_name } }3.2 字段含义解析各字段含义如下表所示字段类型作用说明bundleNamestring应用唯一标识上架与签名都依赖它vendorstring应用开发商名称或公司名versionCodeint版本号数字编码用于系统判断升级versionNamestring版本号显示名称展示给用户iconstring应用图标使用$media:xxx引用labelstring应用名称使用$string:xxx引用3.3 bundleName 命名规范bundleName一旦上架就不能修改否则会被视为新应用。规划时务必谨慎推荐格式com.公司反向域名.产品名 命名约束仅允许小写字母、数字、点号 长度限制7 ~ 128 字符举几个实际例子com.shaohushuo.myapplication小分享 Appcom.huawei.hmos.maps华为地图com.tencent.mm微信四、模块级配置 entry/src/main/module.json54.1 完整配置示例{ module: { name: entry, type: entry, description: $string:module_desc, mainElement: EntryAbility, deviceTypes: [phone], deliveryWithInstall: true, installationFree: false, pages: $profile:main_pages, abilities: [ { name: EntryAbility, srcEntry: ./ets/entryability/EntryAbility.ets, description: $string:EntryAbility_desc, icon: $media:layered_image, label: $string:EntryAbility_label, startWindowIcon: $media:startIcon, startWindowBackground: $color:start_window_background, exported: true, skills: [ { entities: [entity.system.home], actions: [ohos.want.action.home] } ] } ], extensionAbilities: [ { name: EntryBackupAbility, srcEntry: ./ets/entrybackupability/EntryBackupAbility.ets, type: backup, exported: false, metadata: [ { name: ohos.extension.backup, resource: $profile:backup_config } ] } ] } }4.2 关键字段说明模块级配置字段较多重点关注以下几个name模块名工程内唯一type模块类型取值entry/feature/sharedmainElement指定启动时加载的 Ability本工程为EntryAbilitypages指向resources/base/profile/main_pages.json是 ArkUI 路由白名单abilities当前模块的 Ability 列表extensionAbilities扩展 Ability 列表例如备份扩展提示mainElement的值必须与abilities数组中某一项的name完全一致否则会启动失败。五、入口 Ability 实现分析5.1 EntryAbility.ets 完整代码import { AbilityConstant, ConfigurationConstant, UIAbility, Want } from kit.AbilityKit; import { hilog } from kit.PerformanceAnalysisKit; import { window } from kit.ArkUI; const DOMAIN 0x0000; export default class EntryAbility extends UIAbility { onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void { try { this.context.getApplicationContext().setColorMode( ConfigurationConstant.ColorMode.COLOR_MODE_NOT_SET ); } catch (err) { hilog.error(DOMAIN, testTag, Failed to set colorMode. Cause: %{public}s, JSON.stringify(err)); } hilog.info(DOMAIN, testTag, %{public}s, Ability onCreate); } onDestroy(): void { hilog.info(DOMAIN, testTag, %{public}s, Ability onDestroy); } onWindowStageCreate(windowStage: window.WindowStage): void { hilog.info(DOMAIN, testTag, %{public}s, Ability onWindowStageCreate); windowStage.loadContent(pages/Index, (err) { if (err.code) { hilog.error(DOMAIN, testTag, Failed to load: %{public}s, JSON.stringify(err)); return; } hilog.info(DOMAIN, testTag, %{public}s, Succeeded in loading the content.); }); } onWindowStageDestroy(): void { hilog.info(DOMAIN, testTag, %{public}s, Ability onWindowStageDestroy); } onForeground(): void { hilog.info(DOMAIN, testTag, %{public}s, Ability onForeground); } onBackground(): void { hilog.info(DOMAIN, testTag, %{public}s, Ability onBackground); } }5.2 Ability 生命周期回调Ability 提供了 6 个核心生命周期回调开发者按需重写onCreateAbility 实例创建时调用用于初始化全局资源onDestroyAbility 实例销毁时调用用于释放资源onWindowStageCreate窗口舞台创建时调用是加载首个页面的时机onWindowStageDestroy窗口舞台销毁时调用用于释放 UI 资源onForegroundAbility 切到前台时调用可恢复动画、刷新数据onBackgroundAbility 切到后台时调用可暂停耗时任务、释放内存5.3 onCreate 中的颜色模式初始化onCreate中调用setColorMode让颜色模式跟随系统用户在系统设置里切换深色模式App 会自动响应this.context.getApplicationContext().setColorMode( ConfigurationConstant.ColorMode.COLOR_MODE_NOT_SET );ConfigurationConstant.ColorMode的三个取值如下COLOR_MODE_NOT_SET未设置跟随系统COLOR_MODE_DARK强制深色COLOR_MODE_LIGHT强制浅色六、页面注册与路由分发6.1 main_pages.json 路由表resources/base/profile/main_pages.json列出了所有可访问的页面是 ArkUI 路由的「白名单」{ src: [ pages/Index, pages/SplashPage, pages/HomePage, pages/CreateSelectPage, pages/TextEditPage, pages/PreviewPage, pages/TemplateSelectPage, pages/ImageEditPage, pages/LinkEditPage, pages/SharePreviewPage, pages/FavoritesPage, pages/ProfilePage, pages/DiscoverPage, pages/TemplateDetailPage, pages/MoreFunctionsPage, pages/SettingsPage ] }6.2 入口页路由分发入口页pages/Index.ets并不展示任何业务内容只做一次路由跳转import router from ohos.router; Entry Component struct Index { aboutToAppear(): void { router.replaceUrl({ url: pages/SplashPage }); } build() { Column() { Text(小分享) .fontSize(20) .fontWeight(FontWeight.Bold) .fontColor(#1A1A1A) } .width(100%) .height(100%) .justifyContent(FlexAlign.Center) .alignItems(HorizontalAlign.Center) .backgroundColor(Color.White) } }这种「空入口 重定向」的方式便于后续把启动逻辑埋点、版本检查、登录态恢复统一收敛到EntryAbility与Index中。七、整体启动流程架构图小分享 App 的启动流程可以概括为以下链路EntryAbility (Stage 模型入口) │ └─ loadContent(pages/Index) │ └─ replaceUrl(pages/SplashPage) │ └─ setTimeout 2s │ └─ replaceUrl(pages/HomePage) │ └─ BottomTabBar (5 Tab) ├─ HomePage ├─ DiscoverPage ├─ CreateSelectPage () ├─ FavoritesPage └─ ProfilePage提示这种「入口重定向」模式在大型应用中非常常见例如启动时检查登录态未登录则重定向到登录页。八、关键技术点回顾8.1 Stage 模型核心三件套Stage 模型开发的三个核心要素UIAbility承载 UI 与生命周期调度WindowStage窗口舞台管理 UI 渲染目标module.json5模块级配置文件8.2 ArkTS 声明式 UI 范式小分享 App 使用 ArkTS 声明式 UI 范式其核心装饰器如下装饰器作用使用场景Entry标记入口组件每个页面的根组件Component声明自定义组件可复用的 UI 单元State组件内状态需要驱动 UI 刷新的数据Prop单向同步父组件传给子组件的数据Builder构建 UI 片段可复用的 UI 块Watch监听状态变化状态变化时触发副作用8.3 路由 API 对比HarmonyOS 提供三种路由方式// 1. router 路由小分享 App 当前使用 router.pushUrl({ url: pages/HomePage }); router.replaceUrl({ url: pages/HomePage }); router.back(); // 2. Navigation 组件HarmonyOS 推荐方案 const navStack new NavPathStack(); navStack.pushPath({ name: HomePage }); navStack.pop(); // 3. Tabs 组件底部 Tab 切换 Tabs() { TabContent() { HomePage() } TabContent() { DiscoverPage() } }详细的路由 API 说明可参考 HarmonyOS Router 官方文档。九、本篇核心知识点9.1 工程组织规范小分享 App 的工程组织遵循以下规范应用级配置统一放在AppScope主模块放在entry公共类型定义放在common/interfaces.ets自定义组件放在components/页面放在pages/9.2 启动流程要点启动流程要点总结如下EntryAbility是入口负责窗口挂载pages/Index是路由分发节点重定向到启动页main_pages.json统一管理页面路由表启动逻辑埋点、版本检查、登录态恢复建议收敛到EntryAbility与Index总结本文从全景视角拆解了小分享 App 的项目架构涵盖了Stage 模型、UIAbility 生命周期、应用级与模块级配置、页面注册与路由分发等核心知识点。掌握这些基础架构对于后续深入开发至关重要。下一篇我们将深入EntryAbility的生命周期看看onCreate/onWindowStageCreate/onForeground/onBackground之间的时序关系以及如何优雅地处理应用的前后台切换。相关资源HarmonyOS 官方文档HarmonyOS DeveloperArkTS 语法指南ArkTS IntroductionStage 模型开发指南Stage Model Overview开源鸿蒙跨平台社区https://openharmonycrossplatform.csdn.netHarmonyOS GitHub 镜像HarmonyOS Samplesmodule.json5 配置参考Module Configurationapp.json5 配置参考App Configuration如果这篇文章对你有帮助欢迎点赞、收藏⭐、关注你的支持是我持续创作的动力如果这篇文章对你有帮助欢迎点赞、收藏⭐、关注你的支持是我持续创作的动力
HarmonyOS开发实战:小分享-App项目架构全景解析
前言HarmonyOS鸿蒙作为华为自主研发的分布式操作系统正在以惊人的速度占领市场。本文将基于一个真实的鸿蒙原生应用「小分享」从项目架构的全景入手建立对整个工程的认知。小分享是一款支持文字、图片、链接分享的工具类应用使用了 HarmonyOS 最新的ArkTS 声明式开发范式和Stage 模型。本系列共 100 篇文章将从零到一拆解小分享 App 的实现过程涵盖组件、界面编写、状态管理、系统能力集成、性能优化、测试与发布全链路。一、HarmonyOS 开发范式演进1.1 FA 模型与 Stage 模型对比HarmonyOS 应用开发经历了两代模型演进开发者必须清楚两者的差异对比维度FA 模型旧Stage 模型新Ability 类型PageAbility / ServiceAbility / DataAbilityUIAbility / ExtensionAbility配置文件config.jsonmodule.json5开发语言Java / JavaScriptArkTS / CUI 范式基于XML / JavaScript基于ArkTS声明式生命周期复杂多状态简化清晰推荐场景历史遗留项目新项目首选1.2 Stage 模型核心组件Stage 模型主要包含以下核心组件UIAbility承载 UI 的核心组件负责窗口管理与生命周期调度ExtensionAbility扩展能力如备份、卡片、输入法等WindowStage窗口舞台承载所有 UI 内容AbilityLoaderAbility 加载器负责实例化Context上下文对象提供系统能力访问入口二、小分享 App 项目目录结构打开工程根目录xiaofenxiang_ohos_app可以看到如下典型结构xiaofenxiang_ohos_app/ ├── AppScope/ # 应用级配置 │ ├── app.json5 # 应用全局配置 │ └── resources/ # 应用级资源 ├── entry/ # 主模块 │ └── src/ │ ├── main/ │ │ ├── ets/ # ArkTS 源码 │ │ │ ├── common/ # 公共类型定义 │ │ │ ├── components/ # 自定义组件 │ │ │ ├── entryability/ # 入口 Ability │ │ │ └── pages/ # 页面 │ │ ├── module.json5 # 模块配置 │ │ └── resources/ # 模块资源 │ ├── mock/ # Mock 数据 │ └── ohosTest/ # 测试代码 ├── oh-package.json5 # 工程级依赖配置 └── build-profile.json5 # 构建配置这种「AppScope entry 多 HSP/HAR」的结构是 HarmonyOS Stage 模型下的标准工程组织方式。详细工程目录说明可参考 HarmonyOS 官方工程结构文档。三、应用级配置 AppScope/app.json53.1 完整配置文件小分享 App 的应用级配置如下{ app: { bundleName: com.shaohushuo.myapplication, vendor: example, versionCode: 1000000, versionName: 1.0.0, icon: $media:layered_image, label: $string:app_name } }3.2 字段含义解析各字段含义如下表所示字段类型作用说明bundleNamestring应用唯一标识上架与签名都依赖它vendorstring应用开发商名称或公司名versionCodeint版本号数字编码用于系统判断升级versionNamestring版本号显示名称展示给用户iconstring应用图标使用$media:xxx引用labelstring应用名称使用$string:xxx引用3.3 bundleName 命名规范bundleName一旦上架就不能修改否则会被视为新应用。规划时务必谨慎推荐格式com.公司反向域名.产品名 命名约束仅允许小写字母、数字、点号 长度限制7 ~ 128 字符举几个实际例子com.shaohushuo.myapplication小分享 Appcom.huawei.hmos.maps华为地图com.tencent.mm微信四、模块级配置 entry/src/main/module.json54.1 完整配置示例{ module: { name: entry, type: entry, description: $string:module_desc, mainElement: EntryAbility, deviceTypes: [phone], deliveryWithInstall: true, installationFree: false, pages: $profile:main_pages, abilities: [ { name: EntryAbility, srcEntry: ./ets/entryability/EntryAbility.ets, description: $string:EntryAbility_desc, icon: $media:layered_image, label: $string:EntryAbility_label, startWindowIcon: $media:startIcon, startWindowBackground: $color:start_window_background, exported: true, skills: [ { entities: [entity.system.home], actions: [ohos.want.action.home] } ] } ], extensionAbilities: [ { name: EntryBackupAbility, srcEntry: ./ets/entrybackupability/EntryBackupAbility.ets, type: backup, exported: false, metadata: [ { name: ohos.extension.backup, resource: $profile:backup_config } ] } ] } }4.2 关键字段说明模块级配置字段较多重点关注以下几个name模块名工程内唯一type模块类型取值entry/feature/sharedmainElement指定启动时加载的 Ability本工程为EntryAbilitypages指向resources/base/profile/main_pages.json是 ArkUI 路由白名单abilities当前模块的 Ability 列表extensionAbilities扩展 Ability 列表例如备份扩展提示mainElement的值必须与abilities数组中某一项的name完全一致否则会启动失败。五、入口 Ability 实现分析5.1 EntryAbility.ets 完整代码import { AbilityConstant, ConfigurationConstant, UIAbility, Want } from kit.AbilityKit; import { hilog } from kit.PerformanceAnalysisKit; import { window } from kit.ArkUI; const DOMAIN 0x0000; export default class EntryAbility extends UIAbility { onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void { try { this.context.getApplicationContext().setColorMode( ConfigurationConstant.ColorMode.COLOR_MODE_NOT_SET ); } catch (err) { hilog.error(DOMAIN, testTag, Failed to set colorMode. Cause: %{public}s, JSON.stringify(err)); } hilog.info(DOMAIN, testTag, %{public}s, Ability onCreate); } onDestroy(): void { hilog.info(DOMAIN, testTag, %{public}s, Ability onDestroy); } onWindowStageCreate(windowStage: window.WindowStage): void { hilog.info(DOMAIN, testTag, %{public}s, Ability onWindowStageCreate); windowStage.loadContent(pages/Index, (err) { if (err.code) { hilog.error(DOMAIN, testTag, Failed to load: %{public}s, JSON.stringify(err)); return; } hilog.info(DOMAIN, testTag, %{public}s, Succeeded in loading the content.); }); } onWindowStageDestroy(): void { hilog.info(DOMAIN, testTag, %{public}s, Ability onWindowStageDestroy); } onForeground(): void { hilog.info(DOMAIN, testTag, %{public}s, Ability onForeground); } onBackground(): void { hilog.info(DOMAIN, testTag, %{public}s, Ability onBackground); } }5.2 Ability 生命周期回调Ability 提供了 6 个核心生命周期回调开发者按需重写onCreateAbility 实例创建时调用用于初始化全局资源onDestroyAbility 实例销毁时调用用于释放资源onWindowStageCreate窗口舞台创建时调用是加载首个页面的时机onWindowStageDestroy窗口舞台销毁时调用用于释放 UI 资源onForegroundAbility 切到前台时调用可恢复动画、刷新数据onBackgroundAbility 切到后台时调用可暂停耗时任务、释放内存5.3 onCreate 中的颜色模式初始化onCreate中调用setColorMode让颜色模式跟随系统用户在系统设置里切换深色模式App 会自动响应this.context.getApplicationContext().setColorMode( ConfigurationConstant.ColorMode.COLOR_MODE_NOT_SET );ConfigurationConstant.ColorMode的三个取值如下COLOR_MODE_NOT_SET未设置跟随系统COLOR_MODE_DARK强制深色COLOR_MODE_LIGHT强制浅色六、页面注册与路由分发6.1 main_pages.json 路由表resources/base/profile/main_pages.json列出了所有可访问的页面是 ArkUI 路由的「白名单」{ src: [ pages/Index, pages/SplashPage, pages/HomePage, pages/CreateSelectPage, pages/TextEditPage, pages/PreviewPage, pages/TemplateSelectPage, pages/ImageEditPage, pages/LinkEditPage, pages/SharePreviewPage, pages/FavoritesPage, pages/ProfilePage, pages/DiscoverPage, pages/TemplateDetailPage, pages/MoreFunctionsPage, pages/SettingsPage ] }6.2 入口页路由分发入口页pages/Index.ets并不展示任何业务内容只做一次路由跳转import router from ohos.router; Entry Component struct Index { aboutToAppear(): void { router.replaceUrl({ url: pages/SplashPage }); } build() { Column() { Text(小分享) .fontSize(20) .fontWeight(FontWeight.Bold) .fontColor(#1A1A1A) } .width(100%) .height(100%) .justifyContent(FlexAlign.Center) .alignItems(HorizontalAlign.Center) .backgroundColor(Color.White) } }这种「空入口 重定向」的方式便于后续把启动逻辑埋点、版本检查、登录态恢复统一收敛到EntryAbility与Index中。七、整体启动流程架构图小分享 App 的启动流程可以概括为以下链路EntryAbility (Stage 模型入口) │ └─ loadContent(pages/Index) │ └─ replaceUrl(pages/SplashPage) │ └─ setTimeout 2s │ └─ replaceUrl(pages/HomePage) │ └─ BottomTabBar (5 Tab) ├─ HomePage ├─ DiscoverPage ├─ CreateSelectPage () ├─ FavoritesPage └─ ProfilePage提示这种「入口重定向」模式在大型应用中非常常见例如启动时检查登录态未登录则重定向到登录页。八、关键技术点回顾8.1 Stage 模型核心三件套Stage 模型开发的三个核心要素UIAbility承载 UI 与生命周期调度WindowStage窗口舞台管理 UI 渲染目标module.json5模块级配置文件8.2 ArkTS 声明式 UI 范式小分享 App 使用 ArkTS 声明式 UI 范式其核心装饰器如下装饰器作用使用场景Entry标记入口组件每个页面的根组件Component声明自定义组件可复用的 UI 单元State组件内状态需要驱动 UI 刷新的数据Prop单向同步父组件传给子组件的数据Builder构建 UI 片段可复用的 UI 块Watch监听状态变化状态变化时触发副作用8.3 路由 API 对比HarmonyOS 提供三种路由方式// 1. router 路由小分享 App 当前使用 router.pushUrl({ url: pages/HomePage }); router.replaceUrl({ url: pages/HomePage }); router.back(); // 2. Navigation 组件HarmonyOS 推荐方案 const navStack new NavPathStack(); navStack.pushPath({ name: HomePage }); navStack.pop(); // 3. Tabs 组件底部 Tab 切换 Tabs() { TabContent() { HomePage() } TabContent() { DiscoverPage() } }详细的路由 API 说明可参考 HarmonyOS Router 官方文档。九、本篇核心知识点9.1 工程组织规范小分享 App 的工程组织遵循以下规范应用级配置统一放在AppScope主模块放在entry公共类型定义放在common/interfaces.ets自定义组件放在components/页面放在pages/9.2 启动流程要点启动流程要点总结如下EntryAbility是入口负责窗口挂载pages/Index是路由分发节点重定向到启动页main_pages.json统一管理页面路由表启动逻辑埋点、版本检查、登录态恢复建议收敛到EntryAbility与Index总结本文从全景视角拆解了小分享 App 的项目架构涵盖了Stage 模型、UIAbility 生命周期、应用级与模块级配置、页面注册与路由分发等核心知识点。掌握这些基础架构对于后续深入开发至关重要。下一篇我们将深入EntryAbility的生命周期看看onCreate/onWindowStageCreate/onForeground/onBackground之间的时序关系以及如何优雅地处理应用的前后台切换。相关资源HarmonyOS 官方文档HarmonyOS DeveloperArkTS 语法指南ArkTS IntroductionStage 模型开发指南Stage Model Overview开源鸿蒙跨平台社区https://openharmonycrossplatform.csdn.netHarmonyOS GitHub 镜像HarmonyOS Samplesmodule.json5 配置参考Module Configurationapp.json5 配置参考App Configuration如果这篇文章对你有帮助欢迎点赞、收藏⭐、关注你的支持是我持续创作的动力如果这篇文章对你有帮助欢迎点赞、收藏⭐、关注你的支持是我持续创作的动力