HarmonyOS CacheUtil 内存缓存工具:6 个方法让你告别重复计算
文章目录
- 前言
- 一、什么是内存缓存?
- 二、CacheUtil 源码解析
- 三、6 个核心 API 详解
- 3.1 get<T> — 读取缓存
- 3.2 put<T> — 写入缓存
- 3.3 remove — 删除缓存
- 3.4 has — 检查是否存在
- 3.5 isEmpty — 判断缓存是否为空
- 3.6 clear — 清空所有缓存
- 四、完整 Demo 演示
- 4.1 缓存存取操作
- 4.2 读取缓存
- 4.3 删除缓存
- 4.4 清空全部
- 4.5 状态概览 UI
- 五、CacheUtil 在 ClickUtil 中的实战应用
- 六、API 速查表
- 七、注意事项
- 八、小结
前言
近期发现一款很有意思的HarmonyOS 三方库, 地址 @pura/harmony-utils(V1.4.0) , 作者是"桃花镇童长老", 我这里也是直接通过该作者公布的源码进行案例编写进行,写了到目前写了一部分demo ,感觉确实很有帮助,这里呢也是开始写一个系列的演示demo 供大家参考。如有帮助可以在OpenHarmony中进行下载安装进行使用哦
案例demo导航展示
↓↓↓↓↓↓接下来言归正传 ↓↓↓↓
一、什么是内存缓存?
内存缓存(In-Memory Cache)是将数据临时保存在内存中的一种机制。相比每次都从网络、数据库或文件系统获取数据,内存缓存的读取速度快了几个数量级。
常见使用场景:
- 防止重复网络请求:将接口返回的数据缓存,短时间内复用
- 存储计算结果:复杂计算的结果缓存,避免重复运算
- 临时状态共享:不同组件之间传递临时状态(不需要持久化)
- 定时器 ID 管理:
ClickUtil的防抖功能就依赖CacheUtil存储timeoutID
二、CacheUtil 源码解析
CacheUtil使用一个私有的Record<string, Object>作为存储容器:
exportclassCacheUtil{privatestaticcache:Record<string,Object>={};//私有缓存对象Record<string, Object>是 TypeScript/ArkTS 的内置工具类型,相当于一个键为 string、值为任意 Object 类型的字典。整个缓存是类级别的静态变量,也就是说它在 App 运行期间一直存在,在所有组件之间共享同一份缓存。
三、6 个核心 API 详解
效果演示
3.1 get — 读取缓存
staticget<T>(key:string):T{returnCacheUtil.cache[key]asT;}参数:key缓存键名
返回:泛型T,使用时需要指定类型
示例:
consttoken=CacheUtil.get<string>('userToken');constcount=CacheUtil.get<number>('clickCount');constuser=CacheUtil.get<UserInfo>('currentUser');注意:如果 key 不存在,返回
undefined,建议先用has()判断后再取值。
3.2 put — 写入缓存
staticput<T>(key:string,value:T):void{CacheUtil.cache[key]=valueasObject;}参数:
key:缓存键名value:任意类型的值(会被强转为 Object 存储)
示例:
CacheUtil.put<string>('userToken','eyJhbGciOi...');CacheUtil.put<number>('retryCount',3);CacheUtil.put<boolean>('isLoggedIn',true);CacheUtil.put<string[]>('tags',['HarmonyOS','ArkTS']);3.3 remove — 删除缓存
staticremove(key:string){ObjectUtil.deleteRecord(CacheUtil.cache,key);}删除指定键的缓存项。内部委托给ObjectUtil.deleteRecord处理,确保正确删除 Record 中的键。
示例:
CacheUtil.remove('userToken');3.4 has — 检查是否存在
statichas(key:string):boolean{letkeys=Object.keys(CacheUtil.cache);returnkeys.indexOf(key)>=0}返回:如果该 key 存在于缓存中返回true,否则返回false
示例:
if(CacheUtil.has('userToken')){consttoken=CacheUtil.get<string>('userToken');}3.5 isEmpty — 判断缓存是否为空
staticisEmpty():boolean{letkeys=Object.keys(CacheUtil.cache);returnkeys.length<=0;}返回:缓存中没有任何数据时返回true
示例:
if(CacheUtil.isEmpty()){console.log('缓存为空,需要重新加载数据');}3.6 clear — 清空所有缓存
staticclear():void{CacheUtil.cache={};}将缓存对象重置为空对象,所有缓存数据均被清除。
示例:
// 用户退出登录时清空所有缓存CacheUtil.clear();四、完整 Demo 演示
以下代码来自CacheCharClickDemoPage.ets(CacheUtil 部分),展示了完整的缓存操作:
4.1 缓存存取操作
cachePut(){if(this.cacheKeyInput.trim()===''){this.addLog('Cache','Key 不能为空','warn');return;}letvalue:string|number|boolean;if(this.cacheTypeSelect===0){value=this.cacheValueInput;}elseif(this.cacheTypeSelect===1){value=Number(this.cacheValueInput)||0;}else{value=this.cacheValueInput.toLowerCase()==='true';}CacheUtil.put(this.cacheKeyInput.trim(),value);this.addLog('Cache',`put("${this.cacheKeyInput}",${value}) 成功`,'success');this.refreshCacheList();}根据用户选择的类型(String/Number/Boolean),将输入值转换后存入缓存。
4.2 读取缓存
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');}先用has()检查,再用get()读取,是标准的安全读取模式。
4.3 删除缓存
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();}4.4 清空全部
cacheClearAll(){CacheUtil.clear();this.addLog('Cache','clear() 所有缓存已清空','success');this.refreshCacheList();}4.5 状态概览 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)}实时展示缓存是否为空、条目数量、以及特定 key 是否存在。
五、CacheUtil 在 ClickUtil 中的实战应用
CacheUtil的典型应用是为ClickUtil的防抖功能存储定时器 ID:
// ClickUtil.ets 内部staticdebounce(func:()=>void,wait:number=1000,clickId:string=ClickUtil.defaultId){letcacheID=CacheUtil.get<number>(`ClickUtil_debounce_timeoutID_${clickId}`);//获取idif(cacheID!==undefined&&cacheID!==null){clearTimeout(cacheID);}lettimeoutID=setTimeout(()=>{typeoffunc==='function'&&func();clearTimeout(timeoutID);},wait);CacheUtil.put<number>(`ClickUtil_debounce_timeoutID_${clickId}`,timeoutID);//缓存id}这里CacheUtil充当了"全局变量"的角色,通过 key 区分不同的防抖事件,实现了多个独立的防抖定时器管理。
六、API 速查表
| 方法 | 说明 | 返回值 |
|---|---|---|
get<T>(key) | 根据 Key 获取缓存值 | T(可能是 undefined) |
put<T>(key, val) | 存入缓存,值可为任意类型 | void |
remove(key) | 删除指定 Key 的缓存 | void |
has(key) | 判断 Key 是否存在 | boolean |
isEmpty() | 判断缓存是否为空 | boolean |
clear() | 清空所有缓存 | void |
七、注意事项
- 内存缓存不持久化:App 重启后缓存数据丢失,不适合存储需要持久保存的数据(用
PreferencesUtil或AssetUtil) - 类型安全:使用泛型时需要自己保证读取时的类型与存入时一致
- 全局共享:所有组件共享同一份缓存,key 的命名要有语义,避免冲突(如加业务前缀
user_/config_) - 内存占用:频繁存入大对象可能导致内存增长,记得及时
remove或定期clear
八、小结
CacheUtil是一个简单但实用的内存缓存工具:
- 轻量:仅依赖一个
Record对象,无外部依赖 - 泛型支持:
get<T>和put<T>支持存储任意类型 - API 直观:6 个方法对应完整的 CRUD 生命周期
- 内部依赖:
ClickUtil等工具类内部使用,是整个工具集的基础设施
掌握CacheUtil,是理解整个工具集协作机制的重要一步。
