【鸿蒙原生应用开发实战】第一篇:项目初始化与架构设计——从零搭建"阅迹"阅读应用

一、前言

HarmonyOS 自诞生以来,以其分布式架构和全场景能力受到了广泛关注。随着 API 23(HarmonyOS 6.1.0)的发布,Stage 模型进一步完善,ArkTS 语言也日趋成熟。本系列文章将带领大家从零开发一个完整的鸿蒙原生应用——「阅迹」阅读记录与书籍收藏App,手把手讲解每一个技术环节。

本文是第一篇,重点介绍项目初始化、Stage模型架构、数据模型设计以及工程目录规划

二、项目创建与环境配置

2.1 开发环境

  • 操作系统:Windows 11(推荐使用 Windows 10 及以上版本,或 macOS 10.15+,Ubuntu 18.04+)
  • IDE:DevEco Studio 4.1.0+(内置 Node.js 16+ 和 hvigor 构建工具,建议安装时勾选所有相关组件)
  • SDK版本:HarmonyOS API 23(compatibleSdkVersion 23,targetSdkVersion 24)
  • 框架:Stage 模型 + ArkTS(ArkTS 是基于 TypeScript 的声明式 UI 开发框架)
  • 构建工具:hvigor(华为自研构建系统,类似 Gradle,支持增量编译和并行构建)
  • 网络要求:需要稳定的网络连接以下载 SDK 和依赖包,建议配置国内镜像源以加速下载

环境验证步骤

  1. 安装完成后,打开 DevEco Studio,首次启动会自动检测环境
  2. 进入 Configure → Settings → SDK Manager,确保已安装 HarmonyOS SDK 6.1.0
  3. 在终端执行 node -vnpm -v 确认 Node.js 版本(推荐 16.20.2+)
  4. 执行 hvigor -v 检查构建工具版本(推荐 0.6.0+)

2.2 创建项目

在 DevEco Studio 中,选择 File → New → Create Project,进入项目创建向导:

  1. 选择模板:选择 Empty Ability 模板(适合从零开始的项目)

  2. 配置项目

    • Project NameYueJi(阅迹应用)
    • Bundle Namecom.example.yueji(遵循反向域名规范)
    • Save Location:选择合适的工作目录
    • Compile SDK:选择 6.1.0(API 23)
    • Model:选择 Stage Model(推荐新项目使用)
    • Language:选择 ArkTS(鸿蒙原生开发语言)
    • Enable Super Visual:保持默认(开启可视化布局编辑)
    • Device Type:勾选 Phone(手机设备)
  3. 创建完成:点击 Finish,DevEco Studio 会自动下载依赖并初始化项目结构

创建完成后,项目会自动生成以下基础结构:

MyApplication/
├── AppScope/                    # 全局应用配置
│   ├── app.json5                # 应用级配置(bundleName、版本等)
│   └── resources/               # 全局资源(图标、名称等)
├── entry/                       # 应用主模块(可创建多个模块)
│   └── src/main/
│       ├── ets/                 # ArkTS源码目录
│       │   ├── entryability/    # Ability生命周期(EntryAbility.ets)
│       │   ├── pages/           # 页面目录(Index.ets)
│       │   └── common/          # 公共组件和工具类
│       ├── module.json5         # 模块配置文件(页面路由、权限等)
│       └── resources/           # 模块资源(布局、图片、字符串等)
├── build-profile.json5          # 项目级构建配置(SDK版本、签名等)
├── hvigor/                      # 构建配置(hvigorw脚本)
├── .hvigor/                     # 构建缓存目录
└── .idea/                       # IDE配置文件

关键文件说明

  • entry/src/main/ets/entryability/EntryAbility.ets:应用入口,管理应用生命周期
  • entry/src/main/ets/pages/Index.ets:首页UI和逻辑
  • entry/src/main/resources/base/element/string.json:字符串资源文件
  • entry/src/main/resources/base/profile/main_pages.json:页面路由配置

2.3 核心配置文件解读

2.3.1 项目级 build-profile.json5

此文件定义项目级别的构建配置,包括SDK版本、签名信息等:

{
  "app": {
    "signingConfigs": [],          // 签名配置(发布时需要)
    "products": [
      {
        "name": "default",         // 产品名称
        "signingConfig": "default", // 签名配置引用
        "compatibleSdkVersion": "6.1.0(23)",   // 兼容API 23(最低运行版本)
        "targetSdkVersion": "6.1.1(24)",       // 目标API 24(编译目标版本)
        "compileSdkVersion": "6.1.0(23)",      // 编译SDK版本
        "runtimeOS": "HarmonyOS"               // 运行时操作系统
      }
    ]
  },
  "modules": [
    {
      "name": "entry",            // 模块名称
      "srcPath": "./entry",       // 模块路径
      "targets": [
        {
          "name": "default",      // 目标配置
          "applyToProducts": ["default"]
        }
      ]
    }
  ]
}

版本号说明

  • compatibleSdkVersion:应用能运行的最低API版本,向下兼容
  • targetSdkVersion:应用针对的API版本,可使用该版本的所有特性
  • compileSdkVersion:编译时使用的SDK版本
2.3.2 模块级 module.json5

位于 entry/src/main/module.json5,定义模块级配置:

{
  "module": {
    "name": "entry",              // 模块名称
    "type": "entry",              // 模块类型(entry/har/hsp)
    "description": "$string:module_desc", // 模块描述
    "mainElement": "EntryAbility", // 主Ability
    "deviceTypes": ["phone"],     // 支持的设备类型
    "deliveryWithInstall": true,  // 是否随应用安装
    "installationFree": false,    // 是否免安装
    "pages": "$profile:main_pages", // 页面路由配置
    "abilities": [
      {
        "name": "EntryAbility",   // Ability名称
        "srcEntry": "./ets/entryability/EntryAbility.ets",
        "description": "$string:EntryAbility_desc",
        "icon": "$media:icon",
        "label": "$string:EntryAbility_label",
        "startWindowIcon": "$media:icon",
        "startWindowBackground": "$color:start_window_background",
        "exported": true,         // 是否允许外部调用
        "skills": [
          {
            "actions": ["action.system.home"],
            "entities": ["entity.system.home"]
          }
        ]
      }
    ]
  }
}
2.3.3 应用级 app.json5

位于 AppScope/app.json5,定义应用级配置:

{
  "app": {
    "bundleName": "com.example.yueji", // 包名(唯一标识)
    "vendor": "example",               // 厂商名称
    "versionCode": 1000000,            // 版本号(数字)
    "versionName": "1.0.0",            // 版本名称(字符串)
    "icon": "$media:app_icon",         // 应用图标
    "label": "$string:app_name",       // 应用名称
    "description": "$string:app_desc", // 应用描述
    "minAPIVersion": 9,                // 最小API版本
    "targetAPIVersion": 9,             // 目标API版本
    "apiReleaseType": "Release",       // API发布类型
    "debug": true,                     // 调试模式
    "car": {
      "distroFilter": "normal"         // 车机分发过滤
    }
  }
}

配置最佳实践

  1. 版本管理:使用语义化版本控制,每次发布递增 versionCode
  2. 包名规范:使用反向域名格式,确保唯一性
  3. 资源引用:使用 $string:$media:$color: 引用资源,便于国际化
  4. 权限声明:在 module.json5requestPermissions 中声明所需权限

三、Stage 模型架构解析

Stage 模型是 HarmonyOS 自 API 9 引入的新一代 Ability 架构。与旧的 FA 模型相比,Stage 模型有以下核心变化:

3.1 Ability 与页面的关系

EntryAbility (UIAbility)
    └── WindowStage.loadContent('pages/Index')
            ├── Index.ets        ← 首页
            ├── BookListPage.ets  ← 列表页
            ├── BookDetailPage.ets← 详情页
            ├── FavPage.ets       ← 收藏页
            └── ProfilePage.ets   ← 个人中心

EntryAbility.ets 中,通过 onWindowStageCreate 生命周期加载首页:

export default class EntryAbility extends UIAbility {
  onWindowStageCreate(windowStage: window.WindowStage): void {
    windowStage.loadContent('pages/Index', (err) => {
      if (err.code) {
        hilog.error(0x0000, 'testTag', 'Failed: %{public}s', JSON.stringify(err));
        return;
      }
      hilog.info(0x0000, 'testTag', 'Succeeded.');
    });
  }
}

3.2 页面路由配置

所有页面必须在 main_pages.json 中注册:

{
  "src": [
    "pages/Index",
    "pages/BookListPage",
    "pages/BookDetailPage",
    "pages/FavPage",
    "pages/ProfilePage"
  ]
}

四、数据模型设计

作为阅读应用,核心数据是书籍。我设计了一个 Book 接口来标准化数据。

4.1 定义 Book 接口

entry/src/main/ets/model/BookData.ets 中定义:

export interface Book {
  id: number;          // 唯一标识
  title: string;       // 书名
  author: string;      // 作者
  category: string;    // 分类(文学/科技/历史/哲学/艺术)
  rating: number;      // 评分(1.0 - 5.0)
  description: string; // 简介
  year: string;        // 出版年份
  pages: number;       // 页数
  color: string;       // 封面颜色(替代真实图片)
}

为什么不使用真实图片? 在鸿蒙应用开发中,图片资源需要打包到 HAP 中。为了简化示例且不依赖外部图片,我采用纯色背景 + 文字首字作为替代封面方案,既美观又轻量。

4.2 构建书籍数据集

我准备了10本经典书籍,覆盖5个分类:

分类 书籍 作者 评分
文学 百年孤独 马尔克斯 ⭐4.8
文学 活着 余华 ⭐4.9
科技 算法导论 Cormen ⭐4.7
科技 黑客与画家 Paul Graham ⭐4.5
历史 人类简史 赫拉利 ⭐4.8
历史 万历十五年 黄仁宇 ⭐4.6
哲学 存在与时间 海德格尔 ⭐4.3
哲学 庄子 庄子 ⭐4.7
艺术 艺术的故事 贡布里希 ⭐4.9
艺术 美的历程 李泽厚 ⭐4.6

4.3 分类常量与工具函数

export const ALL_CATEGORIES: string[] = ['全部', '文学', '科技', '历史', '哲学', '艺术'];

// 按分类筛选
export function getBooksByCategory(category: string): Book[] {
  if (category === '全部' || category === '') return BOOKS;
  return BOOKS.filter(book => book.category === category);
}

// 获取高分推荐(评分≥4.7)
export function getRecommendedBooks(): Book[] {
  return BOOKS.filter(book => book.rating >= 4.7);
}

// 生成星级字符串
export function getStarString(rating: number): string {
  let stars = '';
  for (let i = 0; i < 5; i++) {
    stars += i < Math.floor(rating) ? '★' : '☆';
  }
  return stars + ' ' + rating.toFixed(1);
}

这里特别要注意的是 ArkTS严格模式 的限制。在 API 23 中,对象字面量必须有显式类型声明(arkts-no-untyped-obj-literals 规则),数组字面量必须可推断类型。因此必须显式标注类型:

// ❌ 错误:缺少类型声明
const books = [{ id: 1, title: '百年孤独' }];

// ✅ 正确:显式声明类型
const BOOKS: Book[] = [{ id: 1, title: '百年孤独', ... }];

五、项目目录结构规划

最终项目的完整目录结构如下:

entry/src/main/ets/
├── entryability/
│   └── EntryAbility.ets          # Ability生命周期
├── entrybackupability/
│   └── EntryBackupAbility.ets    # 备份扩展
├── model/
│   └── BookData.ets              # 数据模型层
└── pages/
    ├── Index.ets                 # 首页
    ├── BookListPage.ets          # 书籍列表
    ├── BookDetailPage.ets        # 书籍详情
    ├── FavPage.ets               # 收藏管理
    └── ProfilePage.ets           # 个人中心

分层设计思想

  • model/:数据层,负责数据定义和查询逻辑,与UI解耦
  • pages/:视图层,每个页面独立文件,通过路由连接
  • entryability/:应用入口,管理生命周期

六、资源文件配置

HarmonyOS 使用资源文件管理颜色、字符串、尺寸等常量,支持多语言和多设备适配。

6.1 颜色资源

{
  "color": [
    { "name": "start_window_background", "value": "#FFF8F0" },
    { "name": "primary_color",           "value": "#C4956A" },
    { "name": "background_color",        "value": "#FFF8F0" },
    { "name": "text_primary",            "value": "#2C1810" },
    { "name": "text_secondary",          "value": "#8B7355" }
  ]
}

6.2 字符串资源

AppScope/resources/string.json 中定义 app_name注意app_name只需在 AppScope 中定义一次,不可在 entry 中重复定义。

6.3 使用资源的最佳实践

在 ArkTS 中通过 $r() 引用资源:

Text('阅迹')
  .fontSize($r('app.float.title_font_size'))
  .fontColor($r('app.color.text_primary'))

七、构建与验证

配置完成后,使用 hvigor 命令构建验证:

cd MyApplication
hvigorw --mode module -p module=entry@default assembleHap

首次构建会启动 hvigor daemon,后续构建会增量执行,速度更快。构建成功的标志是控制台输出 BUILD SUCCESSFUL
在这里插入图片描述

八、小结

本篇完成了:
✅ 项目创建与 SDK 配置
✅ Stage 模型架构理解
✅ 数据模型设计与10本书数据集
✅ 资源文件配置
✅ 项目目录规划

下一篇我们将开始首页开发,实现分类快速入口、精选推荐横向滚动、热门榜单列表以及底部导航栏——敬请期待!


Logo

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

更多推荐