HarmonyOS开发实战:小分享-App项目架构全景解析

前言

HarmonyOS(鸿蒙)作为华为自主研发的分布式操作系统,正在以惊人的速度占领市场。本文将基于一个真实的鸿蒙原生应用「小分享 」,从项目架构的全景入手,建立对整个工程的认知。小分享是一款支持文字、图片、链接分享的工具类应用,使用了 HarmonyOS 最新的 ArkTS 声明式开发范式Stage 模型

本系列共 100 篇文章,将从零到一拆解小分享 App 的实现过程,涵盖组件、界面编写、状态管理、系统能力集成、性能优化、测试与发布全链路。

一、HarmonyOS 开发范式演进

1.1 FA 模型与 Stage 模型对比

HarmonyOS 应用开发经历了两代模型演进,开发者必须清楚两者的差异:

对比维度 FA 模型(旧) Stage 模型(新)
Ability 类型 PageAbility / ServiceAbility / DataAbility UIAbility / ExtensionAbility
配置文件 config.json module.json5
开发语言 Java / JavaScript ArkTS / C++
UI 范式 基于XML / JavaScript 基于ArkTS声明式
生命周期 复杂多状态 简化清晰
推荐场景 历史遗留项目 新项目首选

1.2 Stage 模型核心组件

Stage 模型主要包含以下核心组件:

  • UIAbility:承载 UI 的核心组件,负责窗口管理与生命周期调度
  • ExtensionAbility:扩展能力,如备份、卡片、输入法等
  • WindowStage:窗口舞台,承载所有 UI 内容
  • AbilityLoader:Ability 加载器,负责实例化
  • Context:上下文对象,提供系统能力访问入口

二、小分享 App 项目目录结构

打开工程根目录 xiaofenxiang_ohos_app,可以看到如下典型结构:

text 复制代码
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.json5

3.1 完整配置文件

小分享 App 的应用级配置如下:

json 复制代码
{
  "app": {
    "bundleName": "com.shaohushuo.myapplication",
    "vendor": "example",
    "versionCode": 1000000,
    "versionName": "1.0.0",
    "icon": "$media:layered_image",
    "label": "$string:app_name"
  }
}

3.2 字段含义解析

各字段含义如下表所示:

字段 类型 作用说明
bundleName string 应用唯一标识,上架与签名都依赖它
vendor string 应用开发商名称或公司名
versionCode int 版本号数字编码,用于系统判断升级
versionName string 版本号显示名称,展示给用户
icon string 应用图标,使用 $media:xxx 引用
label string 应用名称,使用 $string:xxx 引用

3.3 bundleName 命名规范

bundleName 一旦上架就不能修改,否则会被视为新应用。规划时务必谨慎:

text 复制代码
推荐格式:com.<公司反向域名>.<产品名>
命名约束:仅允许小写字母、数字、点号
长度限制:7 ~ 128 字符

举几个实际例子:

  • com.shaohushuo.myapplication(小分享 App)
  • com.huawei.hmos.maps(华为地图)
  • com.tencent.mm(微信)

四、模块级配置 entry/src/main/module.json5

4.1 完整配置示例

json 复制代码
{
  "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 / shared
  • mainElement:指定启动时加载的 Ability,本工程为 EntryAbility
  • pages:指向 resources/base/profile/main_pages.json,是 ArkUI 路由白名单
  • abilities:当前模块的 Ability 列表
  • extensionAbilities:扩展 Ability 列表,例如备份扩展

提示:mainElement 的值必须与 abilities 数组中某一项的 name 完全一致,否则会启动失败。

五、入口 Ability 实现分析

5.1 EntryAbility.ets 完整代码

typescript 复制代码
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 个核心生命周期回调,开发者按需重写:

  1. onCreate:Ability 实例创建时调用,用于初始化全局资源
  2. onDestroy:Ability 实例销毁时调用,用于释放资源
  3. onWindowStageCreate:窗口舞台创建时调用,是加载首个页面的时机
  4. onWindowStageDestroy:窗口舞台销毁时调用,用于释放 UI 资源
  5. onForeground:Ability 切到前台时调用,可恢复动画、刷新数据
  6. onBackground:Ability 切到后台时调用,可暂停耗时任务、释放内存

5.3 onCreate 中的颜色模式初始化

onCreate 中调用 setColorMode 让颜色模式跟随系统,用户在系统设置里切换深色模式,App 会自动响应:

typescript 复制代码
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 路由的「白名单」:

json 复制代码
{
  "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 并不展示任何业务内容,只做一次路由跳转:

typescript 复制代码
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)
  }
}

这种「空入口 + 重定向 」的方式便于后续把启动逻辑(埋点、版本检查、登录态恢复)统一收敛到 EntryAbilityIndex 中。

七、整体启动流程架构图

小分享 App 的启动流程可以概括为以下链路:

text 复制代码
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 提供三种路由方式:

typescript 复制代码
// 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 的工程组织遵循以下规范:

  1. 应用级配置统一放在 AppScope
  2. 主模块放在 entry
  3. 公共类型定义放在 common/interfaces.ets
  4. 自定义组件放在 components/
  5. 页面放在 pages/

9.2 启动流程要点

启动流程要点总结如下:

  • EntryAbility 是入口,负责窗口挂载
  • pages/Index 是路由分发节点,重定向到启动页
  • main_pages.json 统一管理页面路由表
  • 启动逻辑(埋点、版本检查、登录态恢复)建议收敛到 EntryAbilityIndex

总结

本文从全景视角拆解了小分享 App 的项目架构,涵盖了 Stage 模型、UIAbility 生命周期、应用级与模块级配置、页面注册与路由分发 等核心知识点。掌握这些基础架构对于后续深入开发至关重要。下一篇我们将深入 EntryAbility 的生命周期,看看 onCreate / onWindowStageCreate / onForeground / onBackground 之间的时序关系,以及如何优雅地处理应用的前后台切换。


相关资源

如果这篇文章对你有帮助,欢迎点赞👍、收藏⭐、关注🔔,你的支持是我持续创作的动力!
如果这篇文章对你有帮助,欢迎点赞👍、收藏⭐、关注🔔,你的支持是我持续创作的动力!

相关推荐
长大19881 小时前
解决 PHP 常见内存溢出问题:从日志定位到代码优化实战
后端
大勇前进1 小时前
Composer 保姆级教程:依赖冲突、版本锁、国内镜像避坑
后端
解局易否结局1 小时前
鸿蒙原生开发实战:Native 图片处理与二维码全链路解析
华为·harmonyos
未秃头的程序猿2 小时前
给公司做了个AI客服Agent,用的Spring AI 1.0,3天上线领导拍板了
java·后端·ai编程
Darren2452 小时前
MySQL索引执行计划不走索引下推
后端
程序员清风2 小时前
OpenAI官方发布最新提示词技巧!
java·后端·面试
码事漫谈2 小时前
人机协同的三重范式:HITL、HOTL与HOOTL
后端
武子康2 小时前
Inkling 975B 说明“开放权重“与“普通开发者本地运行“已经分离,内容重点应是部署容量和运行时边界
前端·人工智能·后端
神奇小汤圆3 小时前
Spring Boot请求处理组件对比详解
后端