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.MediaKit的AVPlayer:
// 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 避免的坑
- 不要修改模板的核心架构层。入口、路由、断点、ViewModel 基类都是经过验证的稳定设计
- 确保新增模块的 oh-package.json5 依赖正确。新增的功能如果依赖 commonLib,需要在对应模块的配置文件中声明
- 数据模型兼容性。WordCard 的数据结构与原有题目类型不同,但通过
IDataSource接口实现了兼容
九、总结
从教育模板到英语学习 App 的改造,我们验证了以下重要结论:
- 模板的价值:好的模板不是一个"Hello World"示例,而是一个经过精心设计、可直接二次开发的工程框架
- 改造的核心:保留架构、替换内容、复用组件、注入领域专属能力
- HarmonyOS 生态优势:ArkTS V2 装饰器体系、响应式布局、声明式路由等特性,让业务改造变得高效而优雅
最终,我们成功将一个通用教育模板改造成了功能完整、体验流畅的英语学习 App——包含 500 词 5 分类词库、卡片翻转学习、语音播报、生词本管理、每日挑战、学习统计等核心功能。