文章目录前言一、引言为什么需要内存缓存二、CacheUtil 工具方法全览三、实战场景详解场景 1缓存网络请求结果避免重复请求场景 2跨页面传递临时状态场景 3防抖函数内部依赖 CacheUtilClickUtil 源码剖析场景 4Demo 页中的缓存读写交互场景 5状态概览 UI 联动四、使用注意事项五、API 快速参考六、小结前言近期发现一款很有意思的HarmonyOS 三方库, 地址 pura/harmony-utils(V1.4.0) , 作者是桃花镇童长老, 我这里也是直接通过该作者公布的源码进行案例编写进行,写了到目前写了一部分demo ,感觉确实很有帮助,这里呢也是开始写一个系列的演示demo 供大家参考。如有帮助可以在OpenHarmony中进行下载安装进行使用哦案例demo导航展示↓↓↓↓↓↓接下来言归正传 ↓↓↓↓一、引言为什么需要内存缓存在开发鸿蒙应用时经常遇到这些痛点同一个接口数据在页面里被反复读取导致多次网络请求用户输入的临时状态如搜索词、表单草稿在页面跳转后丢失ClickUtil.debounce防抖函数内部需要保存timeoutID每次调用都要找个地方存CacheUtil就是解决这些问题的最轻量工具——它本质是一个全局静态Recordstring, Object进程内共享、读写极快、零依赖。二、CacheUtil 工具方法全览在深入实战之前先把所有 API 看一遍// CacheUtil.ets工具类源码exportclassCacheUtil{privatestaticcache:Recordstring,Object{};// 私有缓存对象// 获取缓存中的数据staticgetT(key:string):T{returnCacheUtil.cache[key]asT;}// 将数据存入缓存staticputT(key:string,value:T):void{CacheUtil.cache[key]valueasObject;}// 删除对应的缓存staticremove(key:string){ObjectUtil.deleteRecord(CacheUtil.cache,key);}// 缓存中的数据是否存在statichas(key:string):boolean{letkeysObject.keys(CacheUtil.cache);returnkeys.indexOf(key)0}// 判断缓存是否为空staticisEmpty():boolean{letkeysObject.keys(CacheUtil.cache);returnkeys.length0;}// 清除缓存数据staticclear():void{CacheUtil.cache{};}}关键特性静态类进程级单例所有页面/组件共享同一份缓存泛型getT/putT保证类型安全底层数据结构是Recordstring, Object任何类型都能存三、实战场景详解场景 1缓存网络请求结果避免重复请求// 先检查缓存命中则直接使用constCACHE_KEYuser_profile;asyncfunctiongetUserProfile(userId:string){if(CacheUtil.has(CACHE_KEY)){returnCacheUtil.getUserProfile(CACHE_KEY);}// 未命中发起请求constprofileawaitfetchUserProfile(userId);CacheUtil.putUserProfile(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.keywordCacheUtil.getstring(last_search_keyword);}}利用内存缓存代替路由参数传值适合复杂对象数组、嵌套对象的跨页传递。场景 3防抖函数内部依赖 CacheUtilClickUtil 源码剖析这是 CacheUtil 最经典的内部应用场景——ClickUtil.debounce的实现完全依赖它// ClickUtil.ets工具类源码staticdebounce(func:()void,wait:number1000,clickId:stringClickUtil.defaultId){// 1. 从缓存取出上一次的 timeoutIDletcacheIDCacheUtil.getnumber(ClickUtil_debounce_timeoutID_${clickId});if(cacheID!undefinedcacheID!null){clearTimeout(cacheID);// 2. 清除上一次的定时器}// 3. 创建新的定时器lettimeoutIDsetTimeout((){typeoffuncfunctionfunc();clearTimeout(timeoutID);},wait);// 4. 将新的 timeoutID 存入缓存CacheUtil.putnumber(ClickUtil_debounce_timeoutID_${clickId},timeoutID);}这就是为什么防抖能跨越多次调用记住上一次的定时器——靠的就是 CacheUtil 的全局共享特性。场景 4Demo 页中的缓存读写交互以下是案例 DemoCacheCharClickDemoPage.ets中完整的缓存操作代码// 存入缓存cachePut(){if(this.cacheKeyInput.trim()){this.addLog(Cache,Key 不能为空,warn);return;}letvalue:string|number|boolean;if(this.cacheTypeSelect0){valuethis.cacheValueInput;// String 类型}elseif(this.cacheTypeSelect1){valueNumber(this.cacheValueInput)||0;// Number 类型}else{valuethis.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;}consthasCacheUtil.has(this.cacheKeyInput.trim());if(!has){this.addLog(Cache,Key ${this.cacheKeyInput} 不存在,warn);return;}constvalCacheUtil.getstring|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 快速参考方法说明典型用途putT(key, value)存入任意类型的值缓存接口数据、临时状态getT(key)读取值需提供泛型读接口缓存、读临时状态has(key)检查 key 是否存在缓存命中判断remove(key)删除某个 key数据过期/失效处理isEmpty()检查缓存是否为空UI 状态显示clear()清空全部缓存用户登出、页面重置六、小结CacheUtil是一个设计极简却极为实用的工具类。它的核心价值在于减少 I/O用内存读写替代文件/网络读写跨组件通信充当轻量级全局状态容器支撑其他工具类ClickUtil.debounce的底层就依赖它存储定时器 ID对于小白来说记住这个口诀就够了“存用 put取用 get查用 has删用 remove清用 clear”。