小芽英语鸿蒙开发实战 系列1:全栈架构设计与鸿蒙 Navigation 路由深层博弈

背景介绍

最近家里的孩子上幼儿园了,给报名了个英语延时班,老师要求每天打卡复习。作为老父亲,由于担心自己的"工地英语"发音不标准不敢乱教孩子,每天都只能借助一些现成的 AI 工具来发音让孩子跟读。

但在实际使用中,痛点接踵而至:非常不方便。有时候句子长,或者单词比较拗口的话,孩子根本跟不上;你想让它念得慢点儿,很多工具压根不支持语速调节。

作为一名程序员,遇到痛点当然是自己动手解决。我突然灵机一动:干嘛不自己开发个鸿蒙应用?每天输入每节课的生词和句子,借助鸿蒙系统原生强大的 TTS(文本转语音)能力进行播放,想要多慢就调多慢,让孩子轻松跟读。

需求一旦打开,就一发不可收拾:既然都做了跟读,干嘛不更完善些,把发音打分功能也做上?说干就干!我直接给这个项目起名叫"小芽英语",专为幼儿园孩子量身定制的英语学习打卡神器。

从今天开始,我将把这个应用的完整开发历程------从零代码到端云协同全栈落地,整理成一个系列实战专栏。希望这份真实的"踩坑与避坑指南",能为正在探索 HarmonyOS NEXT 领域的你提供一些极客视角的参考。

1. 架构纵览:端云协同与职责边界

在敲下第一行代码之前,我们必须厘清系统的边界。"小芽英语"虽然界面极简,但其五脏俱全,是一套典型的端云协同系统。

在这个架构中:

  • 鸿蒙客户端:负责儿童友好的沉浸式 UI 展示、调用系统底层 TTS 提供可调速的外教发音、以及接管麦克风录制跟读音频。
  • Java 服务端:基于 Spring Boot 构建,作为安全的网关与 AI 中枢。负责接收来自客户端的 PCM 音频裸流,对接云端的高级语音评测引擎,并将打分结果返回给端侧。

本篇文章,我们将聚焦于鸿蒙端的地基建设:如何规划目录结构 ,以及如何驾驭鸿蒙推荐的最新路由引擎 ------ Navigation

2. 工程地基:清晰的目录结构

在很多初学者的 Demo 中,喜欢把 UI 和逻辑全塞进 pages 目录下。但作为一个商业级项目,我们必须一开始就做到职责分离:

text 复制代码
entry/src/main/ets/
├── pages/          # 页面层:只包含 UI 布局和基础状态维护
│   ├── Index.ets       # 首页:身份选择 (家长端/儿童端)
│   ├── ChildEntry.ets  # 儿童端:卡片跟读、大按钮录音
│   └── ParentEntry.ets # 家长端:表单录入文本
├── utils/          # 工具层:底层能力的封装
│   ├── AudioRecorder.ets   # 麦克风裸流采集封装
│   ├── ScoringApiClient.ets# HTTP 二进制流网络封装
│   └── TTSManager.ets      # 文本转语音引擎单例
└── ...

这种结构的好处是:UI 层不需要关心 PCM 是怎么采样的,也不需要知道网络是怎么重试的。pages 里的组件只管"长得好看"和"响应点击"。

有了页面后,如何把它们串联起来?

在鸿蒙早期版本中,大家习惯使用基于系统 Window 层级的 @ohos.router。但从 API 10 开始,华为官方强烈推荐使用组件级的 Navigation

为什么?因为 Router 每次跳转都会加载完整的页面级环境,开销极大,且无法很好地适应未来多设备(折叠屏、平板)的分栏适配。而 Navigation 作为 ArkUI 的一个普通组件,它的路由跳转本质上只是组件树的局部替换,性能有着质的飞跃。

3.1 搭建根路由栈

Index.ets(我们的入口页面)中,我们首先要初始化一个路由栈 NavPathStack,并通过依赖注入(@Provide)将其共享给所有子页面。

typescript 复制代码
import { ChildEntry } from './ChildEntry';
import { ParentEntry } from './ParentEntry';

@Entry
@Component
struct Index {
  // 【核心机制】:创建路由栈并下发,子页面可通过 @Consume 直接获取
  @Provide('pageStack') pageStack: NavPathStack = new NavPathStack();

  // 路由分发大本营
  @Builder
  PageMap(name: string) {
    if (name === 'ChildEntry') {
      ChildEntry()
    } else if (name === 'ParentEntry') {
      ParentEntry()
    }
  }

  build() {
    Navigation(this.pageStack) {
      Column({ space: 30 }) {
        // ... 欢迎界面与身份选择按钮
        Button('进入儿童跟读')
          .onClick(() => {
            // 路由跳转
            this.pageStack.pushPathByName('ChildEntry', null);
          })
      }
      .width('100%').height('100%')
    }
    // 隐藏自带的标题栏,为了后面实现沉浸式 UI
    .hideTitleBar(true) 
    .navDestination(this.PageMap)
  }
}

底层思路解析

在这段代码中,Navigation 相当于一个容器,navDestination 是路由的"调度员"。当我们调用 pushPathByName 时,框架会去 PageMap 这个建造者(Builder)中寻找匹配的名字,然后原地渲染出 ChildEntry 组件。整个过程不需要通过系统的 WindowManager,因此非常轻量级。

3.2 优雅的安全回退

对于跳转过去的子页面(例如 ChildEntry.ets),它不能像过去使用 router.back() 那样直接调系统 API,而是要使用注入进来的路由栈进行回退。

typescript 复制代码
@Component
export struct ChildEntry {
  // 【核心机制】:通过 @Consume 接收 Index 抛下来的路由栈
  @Consume('pageStack') pageStack: NavPathStack;

  build() {
    NavDestination() {
      Column() {
        // 自定义沉浸式返回按钮
        Image($r('app.media.icon_back'))
          .width(32).height(32)
          .onClick(() => {
            // 安全弹栈
            this.pageStack.pop();
          })
        
        // ... 跟读卡片等业务 UI
      }
    }
    .hideTitleBar(true)
  }
}

避坑指南 :使用 Navigation 时,被路由跳转的子页面最外层必须是 NavDestination 组件 。这是初学者最容易踩坑的地方------如果你最外层直接写个 Column,页面是绝对跳不过来的,并且鸿蒙编译器有时还不会给你明确的报错。

4. 总结

带着为孩子解决真实痛点的初衷,我们的"小芽英语"正式起航。在本篇开局之战中,我们确立了端云协同的底层架构,规划了职责分明的工程目录,并果断抛弃了老旧的 Router,拥抱了代表未来的 Navigation 组件级路由。我们使用依赖注入 (@Provide / @Consume) 的方式,构建了一条干净、安全、高性能的页面导航总线。

但这只是个空架子,一个给儿童用的应用,如果全屏都是灰白色的默认背景,那简直是一场灾难。在下一篇文章中,我们将直面 ArkUI 的渲染引擎,解析如何通过沉浸式属性(expandSafeArea)打破屏幕边界,打造出充满童趣的极客排版与拟物卡片!在这里插入图片描述

相关推荐
AI_零食1 小时前
鸿蒙PC Electron框架天天饮水应用深度解析:健康饮水管理系统
javascript·华为·信息可视化·electron·开源·鸿蒙
坚果派·白晓明1 小时前
鸿蒙PC三方库使用:使用 AtomCode + Skills 自动完成鸿蒙化三方库11Zip集成
c语言·c++·华为·harmonyos
互联网散修1 小时前
鸿蒙实战:图片编辑器——添加文字的UI适配与键盘避让
ui·编辑器·harmonyos
小菜鸟学开发2 小时前
OpenHarmony 编译加速:ccache 使用指南
harmonyos
●VON2 小时前
AtomGit Flutter鸿蒙客户端:OAuth2认证与登录
flutter·华为·跨平台·harmonyos·鸿蒙
小菜鸟学开发2 小时前
OpenHarmony 编译资源复用指南
harmonyos
互联网散修2 小时前
鸿蒙实战:图片编辑器——涂鸦、撤回与保存功能
编辑器·harmonyos·涂鸦·图片编辑
无限码力2 小时前
华为非AI方向0527笔试真题-微服务部署依赖依赖(详细思路+多语言题解)
华为·华为非ai方向笔试真题·华为笔试真题·华为机试真题
●VON2 小时前
AtomGit Flutter鸿蒙客户端:Tab导航架构
flutter·华为·架构·harmonyos·鸿蒙