鸿蒙原生应用实战(一):项目起航 — 从零搭建鸿蒙Stage模型应用框架

本文是「鸿蒙原生应用开发实战」系列第一篇,带你从零搭建一个完整的「心情日记」鸿蒙原生应用,深入理解 Stage 模型、项目目录结构、路由注册机制等核心概念。


一、开篇:为什么选择鸿蒙原生开发?

随着 HarmonyOS 生态的飞速发展,越来越多的开发者开始投身鸿蒙原生应用开发。ArkTS 作为鸿蒙原生开发的主力语言,结合 Stage 模型,提供了一套完整、高效的现代化应用开发框架。

本系列将带领大家从零开发一款完整的「心情日记」应用,涵盖:

  • 首页:今日心情卡片 + 快捷操作入口 + 最近日记列表
  • 写日记:心情选择 + 标题/正文/标签输入
  • 日历视图:月历展示 + 心情标记 + 日记详情
  • 数据统计:总数统计 + 心情分布柱状图 + 近7天心情趋势
  • 个人中心:标签云 + 数据管理 + 导出/重置

二、开发环境准备

2.1 下载 DevEco Studio

访问华为开发者联盟下载最新版 DevEco Studio,安装过程一路 Next 即可。

2.2 配置 SDK

项目使用的 SDK 版本:

compatibleSdkVersion: 6.1.0(23)
targetSdkVersion: 6.1.1(24)

在 DevEco Studio 中通过 Settings → SDK Manager 安装对应版本的 SDK。

2.3 创建项目

打开 DevEco Studio,选择 Create ProjectEmpty Ability,模板选择 Stage 模型 + ArkTS。

![创建项目]

填写项目信息:

  • Project Name: MyApplication
  • Bundle Name: com.example.myapplication
  • Save Location: D:\harmonyos\project\6.11.12345\2\MyApplication
  • Compatible SDK: 6.1.0(23)
  • Device Type: Phone

三、Stage 模型深度解析

3.1 什么是 Stage 模型?

Stage 模型是 HarmonyOS 从 API 9 开始主推的 Ability 框架模型,与旧版的 FA(Feature Ability)模型相比,它有以下几个核心优势:

特性 FA 模型 Stage 模型
组件化管理 ✅ 基于 Module 拆分
生命周期 简单 完善(onCreate → onWindowStageCreate → onForeground → onBackground → onDestroy)
上下文 Context 有限 丰富的 Context API
后台任务 受限 完善的后台任务管理
跨设备迁移 支持有限 原生支持

3.2 Stage 模型的核心概念

┌─────────────────────────────────────┐
│            Application              │
│  ┌──────────────────────────────┐   │
│  │         Module (entry)       │   │
│  │  ┌────────────────────────┐  │   │
│  │  │     UIAbility          │  │   │
│  │  │  - EntryAbility        │  │   │
│  │  │  - EntryBackupAbility  │  │   │
│  │  └────────────────────────┘  │   │
│  │  ┌────────────────────────┐  │   │
│  │  │    Pages (页面)        │  │   │
│  │  │  - Index.ets           │  │   │
│  │  │  - WritePage.ets       │  │   │
│  │  │  - CalendarPage.ets    │  │   │
│  │  │  - StatsPage.ets       │  │   │
│  │  │  - ProfilePage.ets     │  │   │
│  │  └────────────────────────┘  │   │
│  │  ┌────────────────────────┐  │   │
│  │  │     Models (数据)      │  │   │
│  │  │  - DiaryData.ets       │  │   │
│  │  └────────────────────────┘  │   │
│  └──────────────────────────────┘   │
└─────────────────────────────────────┘

3.3 Ability 生命周期

核心的 EntryAbility.ets 中,我们实现了以下生命周期方法:

export default class EntryAbility extends UIAbility {
  onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
    // 应用创建时调用,适合初始化全局数据
    this.context.getApplicationContext().setColorMode(
      ConfigurationConstant.ColorMode.COLOR_MODE_NOT_SET
    );
  }

  onWindowStageCreate(windowStage: window.WindowStage): void {
    // 窗口创建时调用,加载主页面
    windowStage.loadContent('pages/Index', (err) => {
      if (err.code) {
        hilog.error(DOMAIN, 'testTag', 'Failed to load the content');
        return;
      }
    });
  }

  onForeground(): void { /* 应用进入前台 */ }
  onBackground(): void { /* 应用进入后台 */ }
  onDestroy(): void { /* 应用销毁 */ }
}

关键点onWindowStageCreate 中通过 windowStage.loadContent 加载首页,页面路径需与 main_pages.json 中注册的一致。

四、项目目录结构详解

4.1 根目录结构

MyApplication/
├── AppScope/              # 全局应用配置
│   ├── app.json5          # 应用级配置(bundleName, version, icon, label)
│   └── resources/         # 全局资源(string, media等)
├── entry/                 # 主模块
│   ├── src/main/
│   │   ├── ets/           # ArkTS源码
│   │   ├── resources/     # 模块级资源
│   │   └── module.json5   # 模块配置
│   ├── build-profile.json5
│   └── oh-package.json5
├── build-profile.json5    # 项目级构建配置
├── hvigor/                # 构建工具配置
├── oh_modules/            # OHPM依赖
└── local.properties

4.2 源码目录(ets)

ets/
├── entryability/
│   └── EntryAbility.ets       # 应用入口 Ability
├── entrybackupability/
│   └── EntryBackupAbility.ets # 备份恢复 Ability
├── models/
│   └── DiaryData.ets          # 数据模型和工具函数
└── pages/
    ├── Index.ets              # 首页
    ├── WritePage.ets          # 写日记页
    ├── CalendarPage.ets       # 日历视图页
    ├── StatsPage.ets          # 统计页
    └── ProfilePage.ets        # 个人中心页

五、页面路由注册机制

5.1 main_pages.json 配置

entry/src/main/resources/base/profile/main_pages.json 中注册所有页面路由:

{
  "src": [
    "pages/Index",
    "pages/WritePage",
    "pages/CalendarPage",
    "pages/StatsPage",
    "pages/ProfilePage"
  ]
}

注意规则

  • 路径不加 .ets 后缀
  • 首页 Index 必须是第一个
  • module.json5 中通过 "pages": "$profile:main_pages" 引用

5.2 路由跳转实现

鸿蒙中的页面跳转使用 @ohos.router 模块:

import router from '@ohos.router';

// 带参数跳转
router.pushUrl({
  url: 'pages/WritePage',
  params: { from: 'index' }
});

// 返回上一页
router.back();

// 接收参数
const params = router.getParams() as Record<string, Object>;

⚠️ 注意事项(我在开发中踩过的坑):

  1. API 23 下必须从 @ohos.router 导入,@kit.AbilityKit 不导出 router
  2. 页面路径必须与 main_pages.json 中注册的完全一致
  3. router.back() 不带参数直接返回上一页

5.3 module.json5 核心配置

{
  module: {
    name: "entry",
    type: "entry",
    description: "$string:module_desc",
    mainElement: "EntryAbility",
    deviceTypes: ["phone"],
    pages: "$profile:main_pages",
    abilities: [
      {
        name: "EntryAbility",
        srcEntry: "./ets/entryability/EntryAbility.ets",
        exported: true,
        skills: [
          {
            entities: ["entity.system.home"],
            actions: ["ohos.want.action.home"]
          }
        ]
      }
    ]
  }
}

六、构建配置解读

6.1 项目级 build-profile.json5

{
  app: {
    signingConfigs: [],
    products: [
      {
        name: "default",
        targetSdkVersion: "6.1.1(24)",
        compatibleSdkVersion: "6.1.0(23)",
        runtimeOS: "HarmonyOS",
        buildOption: {
          strictMode: {
            caseSensitiveCheck: true,
            useNormalizedOHMUrl: true
          }
        }
      }
    ]
  },
  modules: [{ name: "entry", srcPath: "./entry" }]
}

6.2 模块级 build-profile.json5

{
  apiType: "stageMode",
  buildOption: {
    resOptions: { copyCodeResource: { enable: false } }
  },
  targets: [
    { name: "default" },
    { name: "ohosTest" }
  ]
}

七、构建与运行

7.1 命令行构建

"D:\DevEco Studio\tools\node\node.exe" \
  "D:\DevEco Studio\tools\hvigor\bin\hvigorw.js" \
  --mode module \
  -p module=entry@default \
  -p product=default \
  -p requiredDeviceType=phone \
  assembleHap \
  --analyze=normal --parallel --incremental --daemon

7.2 在 DevEco Studio 中运行

直接在工具栏点击 Run 按钮,选择模拟器或真机设备即可。


八、踩坑记录

🕳️ 坑1:@ohos.router 导入路径

现象:从 @kit.AbilityKit 导入 router 报错
解决:API 23 必须使用 import router from '@ohos.router'

🕳️ 坑2:ArkTS 严格模式

现象:对象字面量报错 arkts-no-untyped-obj-literals
解决:先定义接口再用变量引用

// ❌ 错误
let obj = { name: 'test' };

// ✅ 正确
interface MyObj { name: string; }
let obj: MyObj = { name: 'test' };

🕳️ 坑3:数组字面量类型推断

现象arkts-no-noninferrable-arr-literals
解决:显式指定类型

// ❌ 错误
let arr = [{ id: 1 }, { id: 2 }];

// ✅ 正确
interface Item { id: number; }
let arr: Item[] = [{ id: 1 }, { id: 2 }];

九、下篇预告

至此,我们已经完成了鸿蒙 Stage 模型应用的框架搭建。下一篇将深入探讨数据层设计,包括:

  • 枚举与接口设计的最佳实践
  • AppStorage 全局状态管理
  • 模拟数据生成
  • 工具函数封装

我们将在下一篇中构建起完整的「心情日记」数据模型,为后续页面的开发打下坚实基础。

在这里插入图片描述


如果你在搭建过程中遇到任何问题,欢迎在评论区留言交流。

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐