【OpenHarmony/HarmonyOs 】本地收藏管理实战:ArkTS Service 层实现网址 CRUD 与容错解析
【OpenHarmony/HarmonyOs 】本地收藏管理实战ArkTS Service 层实现网址 CRUD 与容错解析前言当应用允许用户添加收藏后问题就不再只是“把数组显示出来”。我们还要处理空标题、非法链接、重复 URL、旧版本脏数据、排序规则和异常反馈。本文通过EntryManageService展示如何在 ArkTS 中构建一个职责清晰的本地 CRUD 服务。️一、为什么要有 Service 层如果添加、删除、校验和 JSON 解析都写在页面中会出现三个问题多个页面重复规则行为逐渐不一致UI 与数据存储强耦合未来难以迁移 Cloud DB业务逻辑只能通过 UI 测试单元测试成本很高。Service 层让页面只表达意图const service EntryManageService.getInstance(); this.customSites await service.addCustomSite(title,url);至于如何校验、排序和持久化由服务内部负责。二、单例服务与依赖exportclassEntryManageService{privatestaticinstance: EntryManageService;privatestorage: StorageUtil StorageUtil.getInstance();privateconstructor(){}staticgetInstance(): EntryManageService {if(!EntryManageService.instance) { EntryManageService.instance newEntryManageService(); }returnEntryManageService.instance; } }这个服务当前依赖 Preferences。进一步工程化时可以定义SiteRepository接口并注入实现使本地仓库与云仓库可替换。三、读取数据时永远不要信任磁盘内容Preferences 中保存的是 JSON 字符串。应用升级、手动调试或异常中断都可能留下非法数据所以读取过程需要两层防御安全解析和字段规范化。privatesafeParseArray(json:string):Object[] {if(!json)return[];try{constparsed JSON.parse(json)asObject;returnArray.isArray(parsed) ? parsedasObject[] : []; }catch{return[]; } }解析为数组并不代表元素合法还要逐项验证private normalizeUrlItem(raw:Object): UrlItem |null{constitem rawasRawUrlItem;constid typeofitem.id string?item.id:;consttitle typeofitem.title string? item.title.trim() :;consturltypeofitem.url string?this.normalizeHttpsUrl(item.url) :null;if(!id || !title || !url)returnnull;return{ id, title,url,categoryId: item.categoryId ||custom,sort:typeofitem.sort number?item.sort:0,createdAt:typeofitem.createdAt number?item.createdAt:0,updatedAt:typeofitem.updatedAt number?item.updatedAt:0}; }无效项被丢弃缺失的可选字段获得默认值。这能防止一个坏对象让整个收藏页崩溃。四、新增校验、去重、生成元数据asyncaddCustomSite(titleRaw:string,urlRaw:string):PromiseUrlItem[] {consttitle titleRaw.trim();consturlthis.normalizeHttpsUrl(urlRaw);if(!title)thrownewError(EMPTY_TITLE);if(!url)thrownewError(INVALID_URL);constlistawaitthis.listCustomSites();if(list.some(item item.url url)) {thrownewError(DUPLICATE_URL); }constnow Date.now();constnewItem: UrlItem {id:now.toString(), title,url,categoryId:custom,sort:0,createdAt: now,updatedAt: now };constnext [newItem, ...list];awaitthis.persistCustomSites(next);returnnext; }服务返回更新后的数组页面可以一次性替换State触发声明式 UI 刷新。错误使用稳定代码而不是完整中文文案页面可根据场景决定 AlertDialog、Toast 或表单行内提示。时间戳作为 ID 对单机原型足够直观但极端情况下同一毫秒可能冲突。生产项目建议使用 UUID 或由数据库生成主键。五、更新时保留不可变字段更新接口接收 Patch让调用者只传变化部分exportinterfaceUrlItemPatch { title?:string; url?:string; categoryId?:string; sort?:number; }更新后保留原id和createdAt只刷新updatedAt。如果 URL 发生变化还要排除当前记录后再检查重复const duplicate list.some(itemitem.id!iditem.url nextUrl );if(duplicate) throw new Error(DUPLICATE_URL);这是 CRUD 中很常见却容易遗漏的细节。六、删除与排序语义asyncremoveCustomSite(idRaw:string):PromiseUrlItem[] {constid idRaw.trim();if(!id)thrownewError(INVALID_ID);constlist awaitthis.listCustomSites();constnext list.filter(itemitem.id! id);awaitthis.persistCustomSites(next);returnnext; }当前实现对不存在的 ID 采用幂等删除结果仍是成功状态。这对于用户快速重复点击、重试或未来云同步都很友好。读取后按updatedAt降序同一时间再按标题排序能够保证显示结果稳定。稳定排序很重要否则列表可能在每次刷新时随机跳动。七、本地搜索的权重策略Service 为自定义网址提供加权搜索标题前缀 20 分、URL 前缀 10 分、标题包含 5 分、URL 包含 3 分。规则虽然简单却比单纯过滤更符合用户预期。更大规模时可以继续增加拼音首字母访问频率加分最近使用衰减标签匹配用户固定排序优先。八、存储方案的演进边界JSON Preferences 适合 MVP但每次修改都要读写整份数组。当数据量、并发和查询复杂度上升时应迁移PreferencesJSON↓ 数据量增加 ArkData RDB离线结构化查询 ↓ 多设备同步 本地 RDB AGCCloudDB 冲突合并由于页面只依赖 Service替换底层仓库时页面代码可以基本不动这正是分层设计的价值。✅九、总结可靠的收藏功能来自一组明确规则输入先清洗、URL 强制 HTTPS、写入前去重、读取时容错、更新时间可追踪、错误码保持稳定。将这些规则集中到 Service 层可以让 ArkUI 页面保持简洁并为数据库与云同步升级预留空间。

相关新闻

TurboQuant算法:bit级无损量化技术解析与应用

TurboQuant算法:bit级无损量化技术解析与应用

1. TurboQuant算法技术解析TurboQuant算法的核心突破在于实现了bit级别的无损量化,这不同于传统的8-bit或4-bit量化方法。传统量化通常会导致精度损失,而TurboQuant通过创新的权重分组和动态范围调整技术,在保持模型精度的同时实现了显著的加…

2026/7/21 7:46:11 阅读更多 →
华为手机恢复出厂设置全指南与常见问题解决

华为手机恢复出厂设置全指南与常见问题解决

1. 华为手机恢复出厂设置的必要性与适用场景当你的华为手机出现系统卡顿、存储空间不足、应用频繁崩溃或准备转手出售时,恢复出厂设置往往是最彻底的解决方案。我在过去三年间实测了华为Mate 40 Pro/P50 Pro/Mate 60等多款机型,发现90%的软件问题都能通过…

2026/7/21 7:46:11 阅读更多 →
LangChain:大语言模型集成框架的核心技术与应用

LangChain:大语言模型集成框架的核心技术与应用

1. LangChain的崛起背景与技术定位2023年被称为AI应用爆发元年,当ChatGPT引爆全球对大语言模型(LLM)的关注时,开发者们很快发现一个关键矛盾:强大的基础模型与实际业务需求之间存在巨大鸿沟。这正是LangChain诞生的历史…

2026/7/21 7:46:11 阅读更多 →

最新新闻

为什么选择MOSS-Music-8B-Thinking-4bit:Apple Silicon上的最佳音乐AI解决方案

为什么选择MOSS-Music-8B-Thinking-4bit:Apple Silicon上的最佳音乐AI解决方案

为什么选择MOSS-Music-8B-Thinking-4bit:Apple Silicon上的最佳音乐AI解决方案 【免费下载链接】MOSS-Music-8B-Thinking-4bit 项目地址: https://ai.gitcode.com/hf_mirrors/mlx-community/MOSS-Music-8B-Thinking-4bit MOSS-Music-8B-Thinking-4bit是专为…

2026/7/21 16:19:06 阅读更多 →
3分钟让你的GIMP秒变Photoshop:终极界面定制指南

3分钟让你的GIMP秒变Photoshop:终极界面定制指南

3分钟让你的GIMP秒变Photoshop:终极界面定制指南 【免费下载链接】PhotoGIMP A Patch for GIMP 3 for Photoshop Users 项目地址: https://gitcode.com/GitHub_Trending/ph/PhotoGIMP 还在为GIMP的界面布局感到困惑吗?是否怀念Photoshop那熟悉的工…

2026/7/21 16:19:06 阅读更多 →
字节面试官:你的 Agent 系统里面 Skill 是怎么编写的?如何保证高质量的 Skill?

字节面试官:你的 Agent 系统里面 Skill 是怎么编写的?如何保证高质量的 Skill?

在实践中,一般可以通过Skill创建器(例如Codex自带的 Skill Creator),来协助创建Skill,但是高质量的Skill的标准需要我们自己来把关,推荐通过下面五个流程来创建Skill。标准答案参考在实践中,一般…

2026/7/21 16:19:06 阅读更多 →
OpenZFS与ZFS的区别解析:开源存储系统的演进之路

OpenZFS与ZFS的区别解析:开源存储系统的演进之路

OpenZFS与ZFS的区别解析:开源存储系统的演进之路 【免费下载链接】openzfs OpenZFS on Linux and FreeBSD 项目地址: https://gitcode.com/gh_mirrors/op/openzfs 在数据存储领域,OpenZFS与ZFS这两个术语经常让人感到困惑。🤔 许多用户…

2026/7/21 16:19:06 阅读更多 →
jmeter中提取token并设置为全局变量

jmeter中提取token并设置为全局变量

TOCjmeter中提取token并设置为全局变量 jmeter中提取token并设置为全局变量 1. 在测试计划下添加一个setUp Thread Group 2. 在 setUp Thread Group下添加一个登陆的HTTP请求 3. 在HTTP请求下添加一个JSON Extractor // 给JSON Extractor填写信息 token $.data.token4. JSON …

2026/7/21 16:19:06 阅读更多 →
分人群建站解决方案:你是哪种角色?适合你的AI建站方式在这里

分人群建站解决方案:你是哪种角色?适合你的AI建站方式在这里

“工欲善其事,必先利其器。”但对于建站来说,最锋利的“器”,往往取决于你是谁,以及你要用这把“器”来做什么。一个外贸从业者的核心需求,和一个本地花店老板的需求,可能天差地别。这篇指南将针对几种典型…

2026/7/21 16:18:06 阅读更多 →

日新闻

Octane Render与C4D汉化版安装与优化指南

Octane Render与C4D汉化版安装与优化指南

1. Octane Render与C4D的黄金组合:为什么选择这个方案?在三维创作领域,渲染器的选择往往决定了作品的最终呈现质量和工作效率。作为Cinema 4D(C4D)用户,Octane Render的GPU加速特性与实时预览功能&#xff…

2026/7/21 0:00:19 阅读更多 →
GPMC接口设计:异步/同步模式与多路复用配置实战

GPMC接口设计:异步/同步模式与多路复用配置实战

1. GPMC接口设计:从硬件连接到软件配置的全局视角在嵌入式系统开发中,尤其是基于TI Sitara系列如AM263x这类高性能微控制器的项目里,外部存储器的扩展几乎是绕不开的一环。无论是存放大量非易失性代码的NOR Flash,还是作为高速数据…

2026/7/21 0:00:19 阅读更多 →
UE5 GAS框架下RPG被动技能系统:从核心原理到实战实现

UE5 GAS框架下RPG被动技能系统:从核心原理到实战实现

1. 项目概述:UE5 GAS RPG被动技能的核心价值在UE5里用GAS(Gameplay Ability System)做RPG游戏,主动技能像是你手里的武器,按一下打一下,逻辑直接,反馈也快。但被动技能,它更像是你身…

2026/7/21 0:00:19 阅读更多 →

周新闻

Go语言静态资源打包方案对比与实践指南

Go语言静态资源打包方案对比与实践指南

1. 项目背景与核心需求在Go语言开发中,我们经常需要处理静态资源文件的打包问题。无论是Web应用的模板文件、前端资源,还是配置文件、证书等,都需要随程序一起分发。传统做法是将这些文件与编译后的二进制文件放在同一目录下,但这…

2026/7/21 8:48:31 阅读更多 →
Go语言实现高性能LDAP认证服务的架构与实践

Go语言实现高性能LDAP认证服务的架构与实践

1. 项目背景与核心价值LDAP(轻量级目录访问协议)作为企业级身份认证的黄金标准,已经服务了超过80%的财富500强公司。我在金融科技领域实施统一认证体系时,发现传统Java方案存在启动慢、内存占用高等痛点。而Go语言凭借其协程并发模…

2026/7/21 5:34:47 阅读更多 →
【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

更多请点击: https://intelliparadigm.com 第一章:AI面试官实战指南的核心价值与适用场景 AI面试官并非替代人类HR的“黑箱工具”,而是以可解释、可审计、可迭代的方式,赋能招聘全链路的关键基础设施。其核心价值在于将主观经验沉…

2026/7/21 8:25:39 阅读更多 →

月新闻