HarmonyOS 应用开发《掌上英语》第26篇:生词本管理——NewWordManager 的增删改查设计
生词本管理——NewWordManager 的增删改查设计引言在英语学习应用中生词本是一个核心功能模块。用户在学习过程中遇到的生词需要能够方便地收藏、归类、复习并追踪掌握程度。如果设计不当生词本很容易变成收藏即遗忘的死角。本文将以NewWordManager的实现为例展示如何构建一个结构清晰、功能完备的生词本管理模块。一、数据模型设计生词本的核心是NewWordItem数据结构它需要记录生词本身的信息、学习状态和元数据exportinterfaceNewWordItem{keyID:string// 唯一标识用于去重和检索title:string// 单词/词组type:string// 题型类型1:单词拼写 2:听力 等phonetic:string// 音标partOfSpeech:string// 词性example:string// 例句exampleTranslation:string// 例句翻译audioUrl:string// 读音 URLaddTime:number// 添加时间戳masteryLevel:number// 掌握程度0-未掌握 1-熟悉 2-掌握wordPackage:string// 所属词汇包}关键设计决策keyID为主键与题目系统中的TopicItemType.keyID对应确保唯一性。masteryLevel三级制简化掌握程度模型避免过于复杂的记忆曲线计算。wordPackage分类维度支持按词汇包筛选方便用户分类管理。二、单例模式 CRUD 架构NewWordManager采用经典的单例模式通过PreferenceUtil进行数据持久化exportclassNewWordManager{privatestaticinstance?:NewWordManager;privateNEW_WORD_KEYNEW_WORDS;privateconstructor(){}publicstaticgetInstance():NewWordManager{if(!NewWordManager.instance){NewWordManager.instancenewNewWordManager();}returnNewWordManager.instance;}privatesaveNewWords(words:NewWordItem[]):void{PreferenceUtil.getInstance().put(this.NEW_WORD_KEY,words);}}所有数据通过NEW_WORD_KEY存储在PreferenceUtil的默认文件中。saveNewWords作为私有方法封装了写入细节对外只暴露语义化的 CRUD 方法。三、增Create去重添加添加生词时最关键的是去重检查——避免同一单词被重复收藏publicaddNewWord(topicItem:TopicItemType,wordPackage:string默认词汇包):boolean{try{letwords:NewWordItem[]this.getAllNewWords();// 去重检查letexistIndexwords.findIndex(itemitem.keyIDtopicItem.keyID);if(existIndex0){// 已存在则更新添加时间words[existIndex].addTimeDate.now();this.saveNewWords(words);Logger.info(NewWordManager,生词已存在更新时间:${topicItem.keyID});returnfalse;// 返回 false 表示已存在非新增}// 构建新词条letnewWord:NewWordItem{keyID:topicItem.keyID,title:topicItem.title,type:topicItem.type,phonetic:topicItem.ques?.[0]?.phonetic||,partOfSpeech:topicItem.ques?.[0]?.partOfSpeech||,example:topicItem.ques?.[0]?.example||,exampleTranslation:topicItem.ques?.[0]?.exampleTranslation||,audioUrl:topicItem.audioUrl||,addTime:Date.now(),masteryLevel:0,// 默认未掌握wordPackage:wordPackage};words.push(newWord);this.saveNewWords(words);Logger.info(NewWordManager,添加生词成功:${topicItem.title});returntrue;}catch(e){Logger.error(NewWordManager,添加生词失败:${JSON.stringify(e)});returnfalse;}}设计亮点幂等性如果生词已存在不会重复添加而是更新addTime以置顶该词条。默认值兜底topicItem.ques?.[0]?.phonetic || 链式可选访问确保数据不缺失。返回值语义true表示新增成功false表示已存在。四、查Retrieve多维查询// 获取所有生词publicgetAllNewWords():NewWordItem[]{try{letwordsPreferenceUtil.getInstance().get(this.NEW_WORD_KEY,[])asNewWordItem[];returnwords||[];}catch(e){Logger.error(NewWordManager,获取生词列表失败:${JSON.stringify(e)});return[];}}// 按词汇包筛选publicgetNewWordsByPackage(wordPackage:string):NewWordItem[]{try{letwordsthis.getAllNewWords();if(!wordPackage||wordPackage全部){returnwords;}returnwords.filter(itemitem.wordPackagewordPackage);}catch(e){Logger.error(NewWordManager,筛选生词失败:${JSON.stringify(e)});return[];}}// 获取生词数量publicgetNewWordCount():number{returnthis.getAllNewWords().length;}// 检查是否为生词publicisNewWord(keyID:string):boolean{letwordsthis.getAllNewWords();returnwords.some(itemitem.keyIDkeyID);}// 获取所有词汇包名称列表publicgetAllWordPackages():string[]{try{letwordsthis.getAllNewWords();letpackagesnewSetstring();packages.add(全部);words.forEach(item{packages.add(item.wordPackage);});returnArray.from(packages);}catch(e){Logger.error(NewWordManager,获取词汇包列表失败:${JSON.stringify(e)});return[全部];}}查询方法丰富多样getAllNewWords全量查询支持 UI 列表展示排序逻辑。getNewWordsByPackage按词汇包筛选使用filter实现支持全部快捷查询。isNewWord快速判断使用some提前终止遍历。getAllWordPackages使用Set自动去重动态生成分类过滤列表。五、改Update掌握度更新publicupdateMasteryLevel(keyID:string,masteryLevel:number):boolean{try{letwords:NewWordItem[]this.getAllNewWords();letindexwords.findIndex(itemitem.keyIDkeyID);if(index0){words[index].masteryLevelmasteryLevel;this.saveNewWords(words);Logger.info(NewWordManager,更新掌握程度:${keyID}-${masteryLevel});returntrue;}returnfalse;// 词不存在}catch(e){Logger.error(NewWordManager,更新掌握程度失败:${JSON.stringify(e)});returnfalse;}}更新操作采用读取 → 修改 → 全量写回的模式。这是因为 Preferences 是键值存储不支持部分字段更新——我们需要将整个数组读出修改目标项再整体写回。六、删Delete单条删除与清空// 单条删除publicremoveNewWord(keyID:string):boolean{try{letwords:NewWordItem[]this.getAllNewWords();letnewWordswords.filter(itemitem.keyID!keyID);this.saveNewWords(newWords);Logger.info(NewWordManager,移除生词成功:${keyID});returntrue;}catch(e){Logger.error(NewWordManager,移除生词失败:${JSON.stringify(e)});returnfalse;}}// 清空所有publicclearAllNewWords():boolean{try{PreferenceUtil.getInstance().put(this.NEW_WORD_KEY,[]);Logger.info(NewWordManager,清空生词本成功);returntrue;}catch(e){Logger.error(NewWordManager,清空生词本失败:${JSON.stringify(e)});returnfalse;}}删除操作的两种粒度removeNewWord使用filter生成新数组不可变操作不修改原数组。clearAllNewWords直接写入空数组效率最高。七、最佳实践7.1 全量读写的权衡在 Preferences 这样的键值存储中生词列表是以数组形式整体存储的。当生词数量增大时如超过 1000 条全量读写的性能会下降。对于大规模数据建议考虑迁移到关系型数据库如kit.ArkData的 relationalStore。7.2 返回值设计原则所有操作方法统一返回boolean调用方可以据此判断操作结果并给出用户反馈letaddedNewWordManager.getInstance().addNewWord(topicItem);if(added){showToast(已添加到生词本);}else{showToast(该词已在生词本中);}7.3 日志埋点每个关键操作都包含Logger.info/error日志方便调试和用户行为分析。生产环境中可以通过日志平台聚合分析用户添加/删除生词的行为模式。八、总结NewWordManager展示了如何在 HarmonyOS 应用中构建一个具备完整 CRUD 能力的业务 Manager。它通过单例模式管理状态通过PreferenceUtil完成持久化通过清晰的接口设计提供生词的增删改查功能。这种Manager Preferences的轻量级存储模式非常适合小规模业务数据的持久化场景是 HarmonyOS 应用开发中的经典实践。

相关新闻

C++推荐算法工程化:9大核心挑战与高性能推理服务架构实战

C++推荐算法工程化:9大核心挑战与高性能推理服务架构实战

1. 项目概述:当推荐算法遇上C工程化做推荐算法的朋友,尤其是从算法研究转向工程落地的同学,大概都有过这样的经历:在Jupyter Notebook里跑出来的模型AUC高得惊人,各种离线指标一片飘红,感觉马上就要改变世界…

2026/10/4 4:08:03 阅读更多 →
C++组合模式:从核心思想到实战应用,构建灵活可维护的代码结构

C++组合模式:从核心思想到实战应用,构建灵活可维护的代码结构

1. 项目概述:从“组合”说起,为什么它如此重要?最近在社区里看到不少朋友在讨论“C 实现 组合”这个话题,也看到很多相关的搜索热词,从“C map”到“组合服务”,再到“小木棒组合图形”。这让我想起自己刚学…

2026/10/4 14:54:21 阅读更多 →
锁的进阶:自旋锁,死锁与条件变量

锁的进阶:自旋锁,死锁与条件变量

实验环境:VMware VM(4核,Ubuntu 24.04),g 13.2,C17,glibc 2.39 本文分三部分:自旋锁原理与手写实现、死锁复现与 gdb 定位、条件变量与生产者消费者模型。每部分都有完整代码和实验数…

2026/9/27 7:11:08 阅读更多 →

最新新闻

Python GC深度解析:引用计数、分代回收与实战调优

Python GC深度解析:引用计数、分代回收与实战调优

先说我自己的经历。去年排查一个常驻数据服务的RSS内存持续上升问题时,按Java项目的习惯,第一件事就是找GC日志、看GC频率。但Python环境里翻了半天,也没找到什么“GC日志”——Python的GC默认不打印,除非你主动开debug开关。后来…

2026/10/4 14:54:42 阅读更多 →
准静态电磁场:工程中高频与低频之间的黄金建模边界

准静态电磁场:工程中高频与低频之间的黄金建模边界

1. 什么是准静态电磁场:不是“静”也不是“动”,而是工程里最实用的中间态“准静态电磁场”这个词一出来,很多人第一反应是——这不就是静电场或恒定磁场的变体吗?或者干脆觉得是教科书里拗口的理论概念,离实际设计、调…

2026/10/4 14:54:42 阅读更多 →
Claude Code 免费使用指南:用 TaoToken 统一 Key 打通 npm 与 VSCode 配置

Claude Code 免费使用指南:用 TaoToken 统一 Key 打通 npm 与 VSCode 配置

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/4 14:54:42 阅读更多 →
JavaWeb学生信息管理系统:课设完整源码部署与二次开发指南

JavaWeb学生信息管理系统:课设完整源码部署与二次开发指南

简介:基于JavaWeb的学生信息管理系统源码包,面向JavaWeb课程设计与期末项目实践,适合需要完整可运行案例的在校生作为设计参考。压缩包共222个文件,体积约1MB,包含java后端源码、jsp动态页面、js/css与easyui等前端资源…

2026/10/4 14:54:42 阅读更多 →
UniMate单卡运行指南:低显存设备如何跑通首次推理

UniMate单卡运行指南:低显存设备如何跑通首次推理

UniMate单卡运行指南:低显存设备如何跑通首次推理 【免费下载链接】UniMate [SIGGRAPH Asia 2026] UniMate: One Unified Model to Animate Diverse Skeletons 项目地址: https://gitcode.com/GitHub_Trending/un/UniMate UniMate 是 SIGGRAPH Asia 2026 的统…

2026/10/4 14:54:42 阅读更多 →
插件机制深度解析:从加载失败到生命周期排查实战

插件机制深度解析:从加载失败到生命周期排查实战

如果你常年混迹技术社区,会发现“plugins”这个词的出现频率高得吓人——有人问 IAR plugins 是干什么的,有人贴出failed to load plugins web boot: 2 entries did not activate linxin666/dsh-p这种报错求助,还有人讨论 MusicFree 的插件到…

2026/10/4 14:53:41 阅读更多 →

日新闻

KT148A语音芯片外挂8002D功放的工程实践指南

KT148A语音芯片外挂8002D功放的工程实践指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/4 1:00:58 阅读更多 →
LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/4 1:00:58 阅读更多 →
ARM架构深度解析:从RISC设计理念到交叉编译实战

ARM架构深度解析:从RISC设计理念到交叉编译实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/4 1:00:58 阅读更多 →

周新闻

KT148A语音芯片外挂8002D功放的工程实践指南

KT148A语音芯片外挂8002D功放的工程实践指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/4 1:00:58 阅读更多 →
LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/4 1:00:58 阅读更多 →
ARM架构深度解析:从RISC设计理念到交叉编译实战

ARM架构深度解析:从RISC设计理念到交叉编译实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/4 1:00:58 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/4 11:40:45 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/4 9:43:54 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/3 9:42:36 阅读更多 →