HarmonyOS 应用开发《掌上英语》第8篇—项目实践指南

📅 2026/7/17 21:16:56 👁️ 阅读次数 📝 编程学习
HarmonyOS 应用开发《掌上英语》第8篇—项目实践指南

从教育模板到英语学习 App:项目改造实录

一、引言

。本文记录我们如何将一个通用的"教育"模板应用,改造为一款专注于英语学习的 App。改造的核心思路是:保留原有应用架构的精华,注入英语学习领域的专属能力

二、改造前 vs 改造后:功能对照

2.1 首页对比

功能模块模板原有改造后
Banner 轮播考试资讯推荐英语学习功能入口(搜单词、易错词、生词本、学习报告)
推荐课程备考课程列表分类词库展示(基础/CET-4/CET-6/雅思/GRE)
资料下载考试资料学习资料(语法指南、写作模板)
章节练习按章节做题按词库背单词

2.2 答题模块对比

功能模块模板原有改造后
题目类型HarmonyOS 技术题(单选、多选、判断)英语单词认读、拼写
题库内容技术知识点500 词 5 分类英语词库
学习方式标准答题卡片翻转 + 语音播报 + 分类筛选

2.3 我的(个人中心)对比

功能模块模板原有改造后
学习统计做题数量、正确率学习时长、掌握词数、连续打卡
生词本新增:生词管理(加入/移除/掌握度)
学习计划通用计划英语专属计划(每日新词数、复习提醒)
仪表盘通用仪表盘英语学习仪表盘(词库分布、掌握进度)

三、核心改造一:题库替换——从技术题到英语单词

3.1 WordCard 模型设计

改造的第一步,是用英语单词模型替换原有的题目类型。我们创建了WordCard类,使用 ArkTS V2 装饰器确保 UI 响应式:

// commonLib/models/WordCardModel.ets@ObservedV2exportclassWordCard{@Traceid:number=0;@Traceword:string='';// 英语单词@Tracephonetic:string='';// 音标@TracepartOfSpeech:string='';// 词性@Tracetranslation:string='';// 中文释义@Traceexample:string='';// 例句@TraceexampleTranslation:string='';// 例句翻译@TraceaudioUrl:string='';// 音频 URL@Tracetags:string[]=[];// 标签@Tracecategory:string='basic';// 所属分类}

设计要点

  • 每个字段都有@Trace装饰器,当单词的掌握状态变化时,UI 自动刷新
  • audioUrl字段为语音播报预留接口
  • category字段用于分类筛选

3.2 500 词 5 分类词库

我们内置了 500 个单词,分为 5 个难度级别,每个级别 100 个单词:

// 5 个分类的定义exportconstWORD_CATEGORIES:WordCategory[]=[{key:'basic',label:'基础'},// 基础词汇(apple, book, cat...){key:'cet4',label:'CET-4'},// 大学四级(abandon, ability...){key:'cet6',label:'CET-6'},// 大学六级(contradict, controversy...){key:'ielts',label:'雅思'},// 雅思词汇(analyse, apparent...){key:'gre',label:'GRE'},// GRE 词汇(aberration, alacrity...)];

每个单词包含完整的信息:

newWordCard(1,'apple','/ˈæpl/','n.','苹果','I eat an apple every morning for breakfast.','我每天早餐吃一个苹果。','',['日常','食物'],'basic')

3.3 WordCardDataSource:列表数据源

为了使单词数据能够与 LazyForEach / ForEach 配合使用,我们实现了IDataSource接口:

exportclassWordCardDataSourceimplementsIDataSource{privatewords:WordCard[]=[];privatelisteners:DataChangeListener[]=[];constructor(words:WordCard[]){for(leti=0;i<words.length;i++){this.words.push(words[i]);}}publicgetData(index:number):WordCard{returnthis.words[index];}publictotalCount():number{returnthis.words.length;}registerDataChangeListener(listener:DataChangeListener):void{...}unregisterDataChangeListener(listener:DataChangeListener):void{...}}

这样我们就可以使用LazyForEach高效渲染单词列表,即使 500 个单词也能流畅滚动。

四、核心改造二:卡片翻转学习模式

4.1 从 CourseHomePage 到卡片学习

模板中的CourseHomePage原本是课程列表页,改造后成为单词卡片翻转学习的核心页面。卡片翻转的交互逻辑是:

  • 正面:显示英语单词、音标、词性
  • 背面:显示中文释义、例句、例句翻译
  • 点击翻转:用户点击卡片,正反面切换
  • 左右滑动:切换到上一个/下一个单词
// topicPage/Index.etsexport{WordCardPageBuilder}from'./src/main/ets/views/WordCardPage'// 在 WordCardPage 中使用 @State 管理翻转状态@ComponentV2struct WordCardPage{@LocalcurrentIndex:number=0;@LocalisFlipped:boolean=false;// 卡片是否翻转words:WordCard[]=DEFAULT_WORD_CARDS;currentCategory:string='basic';build(){Stack(){// 单词卡片(正反面)CardFront({word:this.currentWord})// 正面:单词 + 音标.opacity(this.isFlipped?0:1)CardBack({word:this.currentWord})// 背面:释义 + 例句.opacity(this.isFlipped?1:0)}.onClick(()=>{this.isFlipped=!this.isFlipped;// 点击翻转}).gesture(SwipeGesture().onAction((event:GestureEvent)=>{if(event.offsetX<0)this.nextWord();// 左滑 → 下一个if(event.offsetX>0)this.prevWord();// 右滑 → 上一个}));}}

4.2 分类筛选

通过分类筛选,用户可以只学习特定难度的词汇:

// 按照分类筛选单词getfilteredWords():WordCard[]{if(this.currentCategory==='all'){returnDEFAULT_WORD_CARDS;}returnDEFAULT_WORD_CARDS.filter(word=>word.category===this.currentCategory);}

分类选择器使用了原有的select_category组件,实现了 UI 复用。

五、核心改造三:语音播报

5.1 AudioPlayer 单例

语音播报是英语学习 App 的标配功能。我们实现了AudioPlayer单例,封装了@kit.MediaKitAVPlayer

// commonLib/utils/AudioPlayer.etsexportclassAudioPlayer{privatestaticinstance?:AudioPlayer;privateavPlayer:media.AVPlayer|null=null;privatecurrentUrl:string='';publicstaticgetInstance():AudioPlayer{if(!AudioPlayer.instance){AudioPlayer.instance=newAudioPlayer();AudioPlayer.instance.initPlayer();// 延迟初始化播放器}returnAudioPlayer.instance;}publicplay(url:string):void{if(!url||url==='')return;// 如果正在播放同一音频,停止if(this.currentUrl===url&&this.avPlayer?.state==='playing'){this.stop();return;}this.currentUrl=url;this.avPlayer?.stop();// 支持网络 URL 和本地 rawfileletsrc=url.startsWith('http')?url:`@rawfile/${url}`;this.avPlayer!.url=src;this.avPlayer!.prepare().then(()=>{this.avPlayer?.play();});}publicstop():void{...}publicpause():void{...}publicrelease():void{...}}

设计亮点

  • 单例模式:全局共用同一个播放器实例,避免多个音频同时播放
  • URL 智能识别:自动区分网络 URL 和本地 rawfile 资源
  • 状态管理play()方法支持"点击暂停、再次点击恢复"的交互

5.2 在卡片翻转中的使用

// 点击喇叭图标播放单词发音Button(){Image($r('app.media.ic_volume'))}.onClick(()=>{if(this.currentWord.audioUrl){AudioPlayer.getInstance().play(this.currentWord.audioUrl);}})

六、核心改造四:生词本管理

6.1 NewWordManager

生词本功能使用NewWordManager单例管理,基于PreferenceUtil实现持久化存储:

// commonLib/utils/NewWordManager.etsexportinterfaceNewWordItem{keyID:stringtitle:string// 单词phonetic:string// 音标partOfSpeech:string// 词性example:string// 例句exampleTranslation:string// 例句翻译audioUrl:string// 音频addTime:number// 添加时间masteryLevel:number// 0:未掌握 1:熟悉 2:掌握wordPackage:string// 所属词汇包}exportclassNewWordManager{privatestaticinstance?:NewWordManager;publicstaticgetInstance():NewWordManager{...}// 添加生词publicaddNewWord(topicItem:TopicItemType,wordPackage:string):boolean{...}// 移除生词publicremoveNewWord(keyID:string):boolean{...}// 获取所有生词publicgetAllNewWords():NewWordItem[]{...}// 按词汇包筛选publicgetNewWordsByPackage(wordPackage:string):NewWordItem[]{...}// 更新掌握程度publicupdateMasteryLevel(keyID:string,masteryLevel:number):boolean{...}// 生词数量publicgetNewWordCount():number{...}}

6.2 与答题模块的集成

生词本功能与答题模块深度集成——在答题页面中,用户可以将不认识的单词一键加入生词本:

// 在答题页面中Button('加入生词本').onClick(()=>{NewWordManager.getInstance().addNewWord(currentTopic,wordPackage);})

生词本页面则展示所有已添加的生词,支持按词汇包筛选和掌握程度排序。

七、其他改造亮点

7.1 首页功能重构

首页从"考试资讯"改为"英语学习功能入口",通过 Banner 展示核心功能:

Banner 轮播: 1. 📖 搜单词 → 调用 SearchPage 2. ⚠️ 易错词 → MyWrongPage(从答题记录中统计的高频错误词) 3. 📝 生词本 → NewWordPage(用户自定义生词) 4. 📊 学习报告 → DashboardPage(学习数据可视化)

7.2 答题模块的题库替换

答题模块的题库从 HarmonyOS 技术题全面替换为英语题目。通过topicPage/Index.ets的导出结构可以看到新增的页面:

// topicPage/Index.ets — 新增的英语学习相关页面export{WordCardPageBuilder}from'./src/main/ets/views/WordCardPage';// 单词卡片export{DailyChallengePageBuilder}from'./src/main/ets/views/DailyChallengePage';// 每日挑战export{SpeechEvalPageBuilder}from'./src/main/ets/views/SpeechEvalPage';// 语音评测

7.3 学习管家功能

新增了学习计划和提醒功能:

  • LearningPlanManager:管理每日学习计划(每日新词数、复习量)
  • ReminderManager:设置学习提醒时间
  • DashboardManager:统计学习数据(连续打卡天数、掌握词数、学习时长)

八、改造经验总结

8.1 保留架构,替换内容

整个改造过程中,我们几乎保留了模板的完整架构(多模块分层、响应式断点、声明式路由),只替换了业务内容。这验证了 HarmonyOS 模板架构设计的通用性和高质量。

8.2 组件复用最大化

answer_questions(答题引擎)、base_select(选择器)、feedback(反馈)等 8 个组件完全复用,不需要修改。这意味着:

  • 模板的组件设计足够抽象,与具体的业务领域解耦
  • 二次开发时可以专注于业务逻辑,无需从零构建基础组件

8.3 新增能力的模块放置

所有新增的英语学习专属能力都放在了合适的位置:

  • 通用能力(WordCard、AudioPlayer、NewWordManager)→commonLib
  • 业务页面(WordCardPage、DailyChallengePage)→topicPage
  • 学习统计(DashboardManager、StatisticsManager)→ 扩展原有 managers

8.4 避免的坑

  1. 不要修改模板的核心架构层。入口、路由、断点、ViewModel 基类都是经过验证的稳定设计
  2. 确保新增模块的 oh-package.json5 依赖正确。新增的功能如果依赖 commonLib,需要在对应模块的配置文件中声明
  3. 数据模型兼容性。WordCard 的数据结构与原有题目类型不同,但通过IDataSource接口实现了兼容

九、总结

从教育模板到英语学习 App 的改造,我们验证了以下重要结论:

  1. 模板的价值:好的模板不是一个"Hello World"示例,而是一个经过精心设计、可直接二次开发的工程框架
  2. 改造的核心:保留架构、替换内容、复用组件、注入领域专属能力
  3. HarmonyOS 生态优势:ArkTS V2 装饰器体系、响应式布局、声明式路由等特性,让业务改造变得高效而优雅

最终,我们成功将一个通用教育模板改造成了功能完整、体验流畅的英语学习 App——包含 500 词 5 分类词库、卡片翻转学习、语音播报、生词本管理、每日挑战、学习统计等核心功能。