鸿蒙原生应用实战(一):项目初始化与Stage模型架构设计
前言
随着HarmonyOS生态的快速发展,越来越多的开发者开始投身鸿蒙原生应用开发。本文将以一个追剧日历 App为实战案例,从零开始讲解如何基于 Stage模型 + ArkTS 构建一个完整的鸿蒙原生应用。
本系列共五篇,覆盖项目初始化、首页开发、搜索与详情页、个人管理与统计、编译构建与性能优化等全流程。
一、项目背景与需求分析
1.1 产品定位
"追剧日历"是一款帮助用户追踪和管理追剧进度的工具类App。核心痛点:追的剧太多,不知道哪天更新、看到哪一集、还剩多少没看。
1.2 功能需求
| 模块 | 功能点 | 说明 |
|---|---|---|
| 首页 | 周历导航、今日更新列表、热门推荐 | 按周切换日期,展示当天更新的剧集,横向滚动热门剧集 |
| 搜索 | 关键词搜索、分类/状态筛选 | 支持按名称模糊搜索,按类型和连载状态过滤 |
| 详情 | 剧集信息、分集列表、收藏、进度追踪 | 动态路由获取剧集ID,展示分集并支持标记已看 |
| 我的追剧 | 三态Tab管理、空状态 | "在看/想看/看完"三Tab,支持快速操作 |
| 统计 | 数据看板、类型分布、月度趋势、成就系统 | 展示追剧总览数据、成就徽章、趋势图 |
1.3 技术选型
- 框架: Stage模型 + ArkTS(声明式UI)
- SDK: API 23(compatibleSdkVersion 23)
- IDE: DevEco Studio
- 页面路由 :
@ohos.router路由跳转 - 资源管理 :
resources/base/element/集中管理字符串、颜色、尺寸
二、项目初始化
2.1 创建项目
在DevEco Studio中:
- 选择 File → New → Create Project
- 选择 Empty Ability 模板(Stage模型)
- 设置项目名称
MyApplication,包名com.example.myapplication - 选择 API 9+ 及以上版本,确保使用Stage模型
2.2 项目目录结构解析
创建完成后,项目结构如下:
MyApplication/
├── AppScope/
│ ├── app.json5 # 全局应用配置
│ └── resources/
│ └── base/element/
│ └── string.json # 全局字符串资源(app_name在此定义)
├── entry/
│ ├── src/main/
│ │ ├── ets/
│ │ │ ├── entryability/ # Ability入口
│ │ │ └── pages/ # 页面文件
│ │ ├── module.json5 # 模块配置文件
│ │ └── resources/ # 页面级资源
│ ├── build-profile.json5 # 模块构建配置
│ └── oh-package.json5 # 依赖管理
├── build-profile.json5 # 项目级构建配置
├── hvigor/
│ └── hvigor-config.json5 # hvigor构建引擎配置
└── oh-package.json5 # 顶层依赖管理
2.3 核心配置文件详解
AppScope/app.json5 ------ 应用级配置
json5
{
"app": {
"bundleName": "com.example.myapplication", // 包名,唯一标识
"vendor": "example", // 供应商
"versionCode": 1000000, // 版本号(整数)
"versionName": "1.0.0", // 版本名
"icon": "$media:layered_image", // 应用图标
"label": "$string:app_name" // 引用全局字符串资源
}
}
注意点:
bundleName是应用唯一标识,发布后不可修改versionCode必须是整数,用于版本对比versionName是面向用户的版本号$string:app_name引用的是AppScope/resources/base/element/string.json中的app_name,不可在entry模块中重复定义
entry/src/main/module.json5 ------ 模块级配置
json5
{
"module": {
"name": "entry",
"type": "entry", // entry类型:可独立安装运行
"mainElement": "EntryAbility",
"deviceTypes": ["phone"], // 支持的设备类型
"pages": "$profile:main_pages.json", // 页面路由注册
"abilities": [
{
"name": "EntryAbility",
"srcEntry": "./ets/entryability/EntryAbility.ets",
"exported": true,
"skills": [
{ "entities": ["entity.system.home"], "actions": ["ohos.want.action.home"] }
]
}
]
}
}
关键理解:
type: "entry"表示这是可独立安装的主模块$profile:main_pages.json引用的是resources/base/profile/下的配置文件skills数组中配置entity.system.home+ohos.want.action.home表示这是桌面启动入口
三、Stage模型详解
3.1 Stage模型 vs FA模型
Stage模型是鸿蒙从API 9开始主推的应用开发模型,与传统的FA模型有显著区别:
| 对比维度 | FA模型 | Stage模型 |
|---|---|---|
| 架构思想 | 以Ability为核心 | 以UIAbility + WindowStage为核心 |
| 生命周期 | Ability生命周期与页面绑定 | 分离Ability与页面生命周期 |
| 页面管理 | 通过AbilitySlice管理 | 通过WindowStage.loadContent加载 |
| 共享实例 | 较难实现 | 通过Context共享 |
| 后台任务 | 能力有限 | 支持ExtensionAbility后台任务 |
3.2 UIAbility生命周期
typescript
// EntryAbility.ets
import { AbilityConstant, ConfigurationConstant, UIAbility, Want } from '@kit.AbilityKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
import { window } from '@kit.ArkUI';
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(0x0000, 'testTag', 'Failed to set colorMode. Cause: %{public}s', JSON.stringify(err));
}
hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate');
}
onWindowStageCreate(windowStage: window.WindowStage): void {
windowStage.loadContent('pages/Index', (err) => {
if (err.code) {
hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err));
return;
}
hilog.info(0x0000, 'testTag', 'Succeeded in loading the content.');
});
}
onForeground(): void { /* 应用进入前台 */ }
onBackground(): void { /* 应用进入后台 */ }
onWindowStageDestroy(): void { /* Window销毁 */ }
onDestroy(): void { /* Ability销毁 */ }
}
生命周期流程:
onCreate → onWindowStageCreate → onForeground → [运行中]
→ onBackground → onForeground → ...
→ onWindowStageDestroy → onDestroy
在 onWindowStageCreate 中通过 windowStage.loadContent() 加载首屏页面,这是我们与UI层交互的入口。
3.3 路由注册方式
页面路由需要在 main_pages.json 中注册:
json
{
"src": [
"pages/Index",
"pages/SearchPage",
"pages/DetailPage",
"pages/MyListPage",
"pages/StatsPage"
]
}
注意 :路径是相对 pages/ 目录的,不需要写 .ets 后缀。
四、资源管理体系
4.1 资源分类
HarmonyOS 资源体系分为三个层级:
-
AppScope全局资源(所有模块共享)
AppScope/resources/base/element/string.json------ 应用名称等
-
模块级资源(当前模块可用)
entry/src/main/resources/base/element/string.json------ 模块描述等entry/src/main/resources/base/element/color.json------ 颜色定义entry/src/main/resources/base/element/float.json------ 尺寸字号定义
-
限定词资源(适配不同设备/语言)
resources/en_US/------ 英文资源resources/zh_CN/------ 中文资源resources/dark/------ 深色模式资源
4.2 资源定义与引用
颜色定义(color.json):
json
{
"color": [
{ "name": "primary_color", "value": "#FF6B35" }, // 主色:活力橙
{ "name": "background_color", "value": "#F5F5F5" }, // 背景色:浅灰
{ "name": "header_bg", "value": "#1A1A2E" } // 头部背景:深色
]
}
尺寸定义(float.json):
json
{
"float": [
{ "name": "title_font_size", "value": "22fp" },
{ "name": "subtitle_font_size", "value": "16fp" },
{ "name": "card_radius", "value": "12vp" },
{ "name": "list_item_height", "value": "80vp" }
]
}
引用方式 :在ArkTS中通过 $r('app.color.primary_color') 或 $r('app.float.title_font_size') 引用。
本项目中我选择了直接使用字面量 的方式(如 '#FF6B35'、16),这在快速原型开发阶段效率更高。进入正式阶段后建议统一迁移到资源文件,便于主题管理和多语言适配。
五、构建配置体系
5.1 API版本配置
在 build-profile.json5(项目级)中配置SDK版本:
json5
{
"app": {
"products": [
{
"name": "default",
"compatibleSdkVersion": "6.1.0(23)", // 兼容最低版本
"targetSdkVersion": "6.1.1(24)", // 目标版本
"runtimeOS": "HarmonyOS"
}
]
}
}
compatibleSdkVersion 决定了你的应用能在什么版本以上的设备运行。设置为API 23意味着兼容较新版本的HarmonyOS设备。
5.2 严格模式
json5
"strictMode": {
"caseSensitiveCheck": true, // 路径大小写敏感检查
"useNormalizedOHMUrl": true // 使用标准化的OHM URL
}
严格模式会在编译时进行更严格的检查,帮助开发者提前发现问题。建议开发阶段开启。
5.3 代码混淆配置
json5
"buildOptionSet": [
{
"name": "release",
"arkOptions": {
"obfuscation": {
"ruleOptions": {
"enable": true, // release包开启混淆
"files": ["./obfuscation-rules.txt"]
}
}
}
}
]
在release构建中开启混淆可以增加逆向难度,保护代码安全。
5.4 hvigor构建引擎
json5
// hvigor/hvigor-config.json5
{
"modelVersion": "6.1.1",
"execution": {
"daemon": true, // 守护进程编译,加速后续构建
"incremental": true, // 增量编译,只编译修改的部分
"parallel": true, // 并行编译,多模块项目更明显
"typeCheck": false // 类型检查(开启会增加编译时间)
}
}
这些构建优化参数对开发体验影响很大:
daemon+incremental组合能显著缩短后续构建时间parallel在多模块项目中优势明显
六、页面架构设计
6.1 五页面路由设计
Index (首页) ←→ SearchPage (搜索)
↓ ↓
DetailPage (详情) ←→ MyListPage (我的追剧)
↓
StatsPage (统计)
6.2 路由导入规范(避坑指南)
API 23(SDK 6.1.0)下路由导入有特殊要求:
typescript
// ✅ 正确方式
import router from '@ohos.router';
// ❌ 错误方式(该版本不导出此路径)
import { router } from '@kit.AbilityKit';
页面跳转:
typescript
// 跳转并传参
router.pushUrl({
url: 'pages/DetailPage',
params: { dramaId: item.id }
});
// 返回上一页
router.back();
// 接收参数
const params: Record<string, Object> = router.getParams() as Record<string, Object>;
const dramaId: number = params['dramaId'] as number;
6.3 接口定义策略
每个页面文件头部定义该页面的数据接口:
typescript
interface Drama {
id: number;
title: string;
cover: string;
genre: string;
episodes: number;
watchedEpisodes: number;
status: string;
rating: number;
updateDay: string;
isNew: boolean;
}
这种文件级接口定义 的方式在小型项目中足够清晰。如果接口被多个页面共享,可以抽离到独立的 types/ 目录。
七、总结
本篇我们完成了:
- ✅ 项目创建与目录结构理解
- ✅ Stage模型核心概念与生命周期
- ✅ 页面路由注册与跳转
- ✅ 资源管理体系搭建
- ✅ 构建配置参数详解
- ✅ 五页面架构设计
下一篇将进入首页开发,深入讲解:
- @Builder装饰器的组件化实践
- List + ForEach实现横向周历
- Scroll + Row实现热门推荐横向滚动
- Progress进度条组件的妙用

SDK版本 : API 23 (HarmonyOS 6.1.0)
框架: Stage模型 + ArkTS