news 2026/7/22 4:51:02

HarmonyOS 应用开发《掌上英语》第26篇:生词本管理——NewWordManager 的增删改查设计

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
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_KEY='NEW_WORDS';privateconstructor(){}publicstaticgetInstance():NewWordManager{if(!NewWordManager.instance){NewWordManager.instance=newNewWordManager();}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();// 去重检查letexistIndex=words.findIndex(item=>item.keyID===topicItem.keyID);if(existIndex>=0){// 已存在则更新添加时间words[existIndex].addTime=Date.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{letwords=PreferenceUtil.getInstance().get(this.NEW_WORD_KEY,[])asNewWordItem[];returnwords||[];}catch(e){Logger.error('NewWordManager',`获取生词列表失败:${JSON.stringify(e)}`);return[];}}// 按词汇包筛选publicgetNewWordsByPackage(wordPackage:string):NewWordItem[]{try{letwords=this.getAllNewWords();if(!wordPackage||wordPackage==='全部'){returnwords;}returnwords.filter(item=>item.wordPackage===wordPackage);}catch(e){Logger.error('NewWordManager',`筛选生词失败:${JSON.stringify(e)}`);return[];}}// 获取生词数量publicgetNewWordCount():number{returnthis.getAllNewWords().length;}// 检查是否为生词publicisNewWord(keyID:string):boolean{letwords=this.getAllNewWords();returnwords.some(item=>item.keyID===keyID);}// 获取所有词汇包名称列表publicgetAllWordPackages():string[]{try{letwords=this.getAllNewWords();letpackages=newSet<string>();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();letindex=words.findIndex(item=>item.keyID===keyID);if(index>=0){words[index].masteryLevel=masteryLevel;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();letnewWords=words.filter(item=>item.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,调用方可以据此判断操作结果并给出用户反馈:

letadded=NewWordManager.getInstance().addNewWord(topicItem);if(added){showToast('已添加到生词本');}else{showToast('该词已在生词本中');}

7.3 日志埋点

每个关键操作都包含Logger.info/error日志,方便调试和用户行为分析。生产环境中可以通过日志平台聚合分析用户添加/删除生词的行为模式。

八、总结

NewWordManager展示了如何在 HarmonyOS 应用中构建一个具备完整 CRUD 能力的业务 Manager。它通过单例模式管理状态,通过PreferenceUtil完成持久化,通过清晰的接口设计提供生词的增删改查功能。这种"Manager + Preferences"的轻量级存储模式非常适合小规模业务数据的持久化场景,是 HarmonyOS 应用开发中的经典实践。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/22 4:49:38

德州仪器ISS ISP硬件编程实战:ISIF与IPIPEIF模块配置与调试指南

1. 项目概述&#xff1a;深入德州仪器ISS ISP的硬件编程核心在嵌入式视觉系统的开发中&#xff0c;图像信号处理器&#xff08;ISP&#xff09;扮演着将原始传感器数据“翻译”成人类可理解图像的关键角色。这不仅仅是简单的格式转换&#xff0c;而是一系列精密、实时的硬件级运…

作者头像 李华
网站建设 2026/7/22 4:48:20

Claude Code:AI编程助手的核心技术解析与应用实践

1. Claude Code项目概览与技术定位Claude Code作为新一代AI编程助手&#xff0c;其核心设计理念是成为开发者工作流中的"数字协作者"。与传统的代码补全工具不同&#xff0c;它采用全代码库感知架构&#xff0c;通过静态分析、动态追踪和上下文建模三大技术支柱&…

作者头像 李华
网站建设 2026/7/22 4:48:09

Linux运维工程师必备工具链与实战技巧

1. Linux运维工程师的软件武器库 作为一名在运维战线摸爬滚打多年的老兵&#xff0c;我深知选择趁手的工具对工作效率的影响有多大。就像木匠需要一套好用的凿子和锯子&#xff0c;Linux运维工程师也需要精心打造自己的软件工具箱。不同于普通用户&#xff0c;运维工作的特殊性…

作者头像 李华
网站建设 2026/7/22 4:47:34

2026 LangChain 入门:环境搭建 + 国产大模型调用与消息结构全解

一、前言&#xff08;CSDN 标准引流开头&#xff09;本文旨在解决这些痛点&#xff0c;为零基础开发者提供一份2026年最新的LangChain入门指南。我们将聚焦两大核心模块&#xff1a;环境搭建和模型调用&#xff0c;并深入解析LangChain的消息结构机制&#xff0c;这是后续学习R…

作者头像 李华
网站建设 2026/7/22 4:46:03

C/C++邮件发送库jwsmtp:轻量级SMTP客户端集成与实战指南

1. 项目概述&#xff1a;为什么我们需要一个纯粹的C/C邮件发送库&#xff1f;在嵌入式开发、高性能服务器后台或者一些对运行时环境有严格限制的C/C项目中&#xff0c;实现一个发送邮件的功能&#xff0c;听起来简单&#xff0c;做起来却常常让人头疼。你可能会想&#xff0c;直…

作者头像 李华
网站建设 2026/7/22 4:45:04

刚入职的软件工程师,如何把项目踩坑整理成高质量技术博客

摘要作为一名刚入职的软件开发工程师&#xff0c;我最近开始思考一件事&#xff1a;技术博客到底应该写什么&#xff1f;一开始我也想过写一些通用教程&#xff0c;比如某个工具怎么安装、某门语言怎么入门、某个框架怎么使用。但后来我发现&#xff0c;真正有价值、也更容易被…

作者头像 李华