当前位置: 首页 > news >正文

HarmonyOS ArkTS CacheUtil 内存缓存实战场景全解析

文章目录

    • 前言
    • 一、引言:为什么需要内存缓存?
    • 二、CacheUtil 工具方法全览
    • 三、实战场景详解
      • 场景 1:缓存网络请求结果(避免重复请求)
      • 场景 2:跨页面传递临时状态
      • 场景 3:防抖函数内部依赖 CacheUtil(ClickUtil 源码剖析)
      • 场景 4:Demo 页中的缓存读写交互
      • 场景 5:状态概览 UI 联动
    • 四、使用注意事项
    • 五、API 快速参考
    • 六、小结

前言

近期发现一款很有意思的HarmonyOS 三方库, 地址 @pura/harmony-utils(V1.4.0) , 作者是"桃花镇童长老", 我这里也是直接通过该作者公布的源码进行案例编写进行,写了到目前写了一部分demo ,感觉确实很有帮助,这里呢也是开始写一个系列的演示demo 供大家参考。如有帮助可以在OpenHarmony中进行下载安装进行使用哦

案例demo导航展示

↓↓↓↓↓↓接下来言归正传 ↓↓↓↓

一、引言:为什么需要内存缓存?

在开发鸿蒙应用时,经常遇到这些痛点:

  • 同一个接口数据在页面里被反复读取,导致多次网络请求
  • 用户输入的临时状态(如搜索词、表单草稿)在页面跳转后丢失
  • ClickUtil.debounce防抖函数内部需要保存timeoutID,每次调用都要找个地方存

CacheUtil就是解决这些问题的最轻量工具——它本质是一个全局静态Record<string, Object>,进程内共享、读写极快、零依赖。


二、CacheUtil 工具方法全览

在深入实战之前,先把所有 API 看一遍:

// CacheUtil.ets(工具类源码)exportclassCacheUtil{privatestaticcache:Record<string,Object>={};// 私有缓存对象// 获取缓存中的数据staticget<T>(key:string):T{returnCacheUtil.cache[key]asT;}// 将数据存入缓存staticput<T>(key:string,value:T):void{CacheUtil.cache[key]=valueasObject;}// 删除对应的缓存staticremove(key:string){ObjectUtil.deleteRecord(CacheUtil.cache,key);}// 缓存中的数据是否存在statichas(key:string):boolean{letkeys=Object.keys(CacheUtil.cache);returnkeys.indexOf(key)>=0}// 判断缓存是否为空staticisEmpty():boolean{letkeys=Object.keys(CacheUtil.cache);returnkeys.length<=0;}// 清除缓存数据staticclear():void{CacheUtil.cache={};}}

关键特性

  • 静态类,进程级单例,所有页面/组件共享同一份缓存
  • 泛型get<T>/put<T>保证类型安全
  • 底层数据结构是Record<string, Object>,任何类型都能存

三、实战场景详解

场景 1:缓存网络请求结果(避免重复请求)

// 先检查缓存,命中则直接使用constCACHE_KEY='user_profile';asyncfunctiongetUserProfile(userId:string){if(CacheUtil.has(CACHE_KEY)){returnCacheUtil.get<UserProfile>(CACHE_KEY);}// 未命中,发起请求constprofile=awaitfetchUserProfile(userId);CacheUtil.put<UserProfile>(CACHE_KEY,profile);returnprofile;}

第一次调用发网络请求并写入缓存,后续调用直接从内存读取,速度提升数十倍。


场景 2:跨页面传递临时状态

// 页面 A:搜索页,用户输入关键词后跳转CacheUtil.put('last_search_keyword',this.searchInput);router.pushUrl({url:'pages/SearchResult'});// 页面 B:结果页,恢复上次的搜索词aboutToAppear(){if(CacheUtil.has('last_search_keyword')){this.keyword=CacheUtil.get<string>('last_search_keyword');}}

利用内存缓存代替路由参数传值,适合复杂对象(数组、嵌套对象)的跨页传递。


场景 3:防抖函数内部依赖 CacheUtil(ClickUtil 源码剖析)

这是 CacheUtil 最经典的内部应用场景——ClickUtil.debounce的实现完全依赖它:

// ClickUtil.ets(工具类源码)staticdebounce(func:()=>void,wait:number=1000,clickId:string=ClickUtil.defaultId){// 1. 从缓存取出上一次的 timeoutIDletcacheID=CacheUtil.get<number>(`ClickUtil_debounce_timeoutID_${clickId}`);if(cacheID!==undefined&&cacheID!==null){clearTimeout(cacheID);// 2. 清除上一次的定时器}// 3. 创建新的定时器lettimeoutID=setTimeout(()=>{typeoffunc==='function'&&func();clearTimeout(timeoutID);},wait);// 4. 将新的 timeoutID 存入缓存CacheUtil.put<number>(`ClickUtil_debounce_timeoutID_${clickId}`,timeoutID);}

这就是为什么防抖能跨越多次调用"记住"上一次的定时器——靠的就是 CacheUtil 的全局共享特性。


场景 4:Demo 页中的缓存读写交互

以下是案例 Demo(CacheCharClickDemoPage.ets)中完整的缓存操作代码:

// 存入缓存cachePut(){if(this.cacheKeyInput.trim()===''){this.addLog('Cache','Key 不能为空','warn');return;}letvalue:string|number|boolean;if(this.cacheTypeSelect===0){value=this.cacheValueInput;// String 类型}elseif(this.cacheTypeSelect===1){value=Number(this.cacheValueInput)||0;// Number 类型}else{value=this.cacheValueInput.toLowerCase()==='true';// Boolean 类型}CacheUtil.put(this.cacheKeyInput.trim(),value);this.addLog('Cache',`put("${this.cacheKeyInput}",${value}) 成功`,'success');this.refreshCacheList();}// 读取缓存cacheGet(){if(this.cacheKeyInput.trim()===''){this.addLog('Cache','请输入 Key','warn');return;}consthas=CacheUtil.has(this.cacheKeyInput.trim());if(!has){this.addLog('Cache',`Key "${this.cacheKeyInput}" 不存在`,'warn');return;}constval=CacheUtil.get<string|number|boolean>(this.cacheKeyInput.trim());this.addLog('Cache',`get("${this.cacheKeyInput}") =${val}`,'success');}// 删除缓存cacheRemove(){if(this.cacheKeyInput.trim()===''){this.addLog('Cache','请输入 Key','warn');return;}CacheUtil.remove(this.cacheKeyInput.trim());this.addLog('Cache',`remove("${this.cacheKeyInput}") 已删除`,'success');this.refreshCacheList();}// 清空全部缓存cacheClearAll(){CacheUtil.clear();this.addLog('Cache','clear() 所有缓存已清空','success');this.refreshCacheList();}

场景 5:状态概览 UI 联动

Demo 中展示了如何用 CacheUtil API 驱动 UI 状态显示:

// UI 中实时读取缓存状态Row(){Column(){Text(`${CacheUtil.isEmpty()?'⏸️ 空':'📦 有数据'}`).fontSize(13).fontWeight(FontWeight.Bold).fontColor(CacheUtil.isEmpty()?'#FF9800':'#00C853')Text('缓存状态').fontSize(11).fontColor('#888')}.layoutWeight(1)Column(){Text(`${this.cacheEntries.length}`).fontSize(13).fontWeight(FontWeight.Bold).fontColor('#4080FF')Text('条目数').fontSize(11).fontColor('#888')}.layoutWeight(1)Column(){Text(CacheUtil.has('test_key')?'✅':'❌').fontSize(13)Text('has(test_key)').fontSize(11).fontColor('#888')}.layoutWeight(1)}.width('100%').padding(14).backgroundColor('#FFFFFF').borderRadius(12)

CacheUtil.isEmpty()决定显示"⏸️ 空"还是"📦 有数据",has('test_key')实时检查特定 key 是否存在。

四、使用注意事项

注意点说明
进程级缓存应用重启后缓存清空,不适合持久化数据(用 Preferences/Asset)
内存占用不要存入大量大体积对象,建议只存关键状态数据
线程安全ArkTS 主线程执行,不存在竞态问题
Key 命名建议用常量定义 key,避免拼写错误(如const USER_KEY = 'user_profile'
生命周期建议在页面销毁时主动remove不再需要的缓存

五、API 快速参考

方法说明典型用途
put<T>(key, value)存入任意类型的值缓存接口数据、临时状态
get<T>(key)读取值,需提供泛型读接口缓存、读临时状态
has(key)检查 key 是否存在缓存命中判断
remove(key)删除某个 key数据过期/失效处理
isEmpty()检查缓存是否为空UI 状态显示
clear()清空全部缓存用户登出、页面重置

六、小结

CacheUtil是一个设计极简却极为实用的工具类。它的核心价值在于:

  1. 减少 I/O:用内存读写替代文件/网络读写
  2. 跨组件通信:充当轻量级全局状态容器
  3. 支撑其他工具类ClickUtil.debounce的底层就依赖它存储定时器 ID

对于小白来说,记住这个口诀就够了:“存用 put,取用 get,查用 has,删用 remove,清用 clear”

http://www.jsqmd.com/news/874543/

相关文章:

  • 【Java后端开发】花了2k+多的人民币,烧了几十亿Token,慢慢整理出来适用于Java开发人员的codex配置,还在持续优化中
  • 3步快速上手SSDD:合成孔径雷达舰船检测终极指南
  • 深圳企业如何在AI搜索浪潮中抢占认知高地:GEO优化实战路径与服务商选型指南 - GEO优化
  • C51编译器局部变量存储优化与寄存器分配解析
  • SqueezeBERT:借CV分组卷积为NLP模型瘦身,实现移动端4.3倍加速
  • 大模型知识大观:从数学基础到应用落地的完整图谱
  • 3步解锁Windows远程桌面多人连接:RDP Wrapper Library完整指南
  • 2026长三角正规月嫂培训优质机构推荐榜:哈柏母婴职业教育、哈柏培训学校、哈柏母婴培训学校、哈柏母婴职业技能培训学校选择指南 - 优质品牌商家
  • 如何让 RAG 支持跨语言查询(如中文问题检索英文文档)?
  • C#中Jobject转string方法实现
  • YOLACT实战:从训练到部署,让你的模型在图片和视频上实时跑起来(Python/OpenCV)
  • 链表数据结构预取技术Linkey的设计与优化
  • 保姆级教程:为你的Avalonia(.NET6)应用制作银河麒麟V10专属deb安装包(含字体修复)
  • 使用C#代码在Excel中获取工作表名称的操作指南
  • ST uPSD33xx芯片Keil断点失效问题解析与解决
  • 2026年GEO优化公司权威推荐与全意图GEO战略价值深度分析 - GEO优化
  • 电力变压器油温预测实战:如何用ETT数据集训练你的第一个LSTM模型
  • d2dx终极教程:三步让暗黑破坏神2在现代PC上焕然一新
  • 面向对象分析学习笔记:形式化方法初探与《大象——Thinking in UML》阅读心得
  • 别再复制粘贴了!Ubuntu 22.04 LTS上手动编译OpenFOAM v2206的保姆级避坑指南
  • 从零搭建私有化播客TTS流水线:Docker+TensorRT加速+实时情感注入(企业级部署手册·限免72小时)
  • SEAM方法:利用灾难性遗忘实现模型后门攻击的盲净化
  • 2026成都河堤栏杆优质厂家推荐适配多场景:成都河道栏杆厂家/成都混凝土栏杆厂家/景区栈道仿木护栏/景区栈道仿木栏杆/选择指南 - 优质品牌商家
  • 从零搭建一个AI应用:用Python+Milvus快速构建你的第一个图像检索系统
  • DeepSeek-V4-Pro 技术实测:开源旗舰的能力再平衡与工程效率革命
  • 我的毕业设计:用SVM给微博评论‘看相’,从爬虫到部署的踩坑实录
  • 基于SpringBoot的智能仓储WMS毕设
  • 【Claude项目管理实战指南】:20年PM专家亲授5大高阶提示词技巧,90%团队效率提升3倍的秘密
  • Midjourney复古风格失效的5个致命陷阱(2024最新算法适配失效预警)
  • 2026年质量好的全屋定制综合评价公司 - 品牌宣传支持者