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

HarmonyOS 全局缓存不乱:GlobalContext Key 管理与泛型安全取值模式

文章目录

    • 前言
      • 案例预览
      • 问题一:Key 是魔法字符串,容易拼错
      • 问题二:取值不判空,直接用会崩
      • 问题三:取出来是 Object,用时要类型断言
      • 推荐的封装模式
      • 退出登录的正确姿势
      • 写在最后

前言

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

案例demo导航展示

↓↓↓↓↓↓接下来言归正传 ↓↓↓↓
上一篇把 GlobalContext 的 API 全部过了一遍,这篇聊点更实际的:在真实项目里怎么用才不会搞乱

GlobalContext 用起来简单,但正是因为简单,很容易被滥用——Key 随便起名,取值不判空,到处散落……时间一长,维护起来一团糟。

案例预览

问题一:Key 是魔法字符串,容易拼错

最常见的用法是直接传字符串:

// ❌ 不推荐:魔法字符串,容易拼错GlobalContext.getContext().put('userToken',token);// 另一个文件里取值consttoken=GlobalContext.getContext().get<string>('userTocken');// 拼错了!

拼写错误是 Key-Value 存储最常见的 bug,而且编译时不报错,运行时才发现。

推荐做法:创建一个常量文件统一管理 Key:

// GlobalContextKeys.tsexportconstGlobalKeys={IS_LOGIN:'isLogin',TOKEN:'token',USER_NAME:'userName',USER_ID:'userId',TIMESTAMP:'timestamp',};

然后所有地方都用这些常量:

// 写入时用常量GlobalContext.getContext().put(GlobalKeys.TOKEN,'Bearer eyJhbGci.example');// 读取时也用常量consttoken=GlobalContext.getContext().get<string>(GlobalKeys.TOKEN);

常量名拼错了编译时就报错,比字符串安全得多。

问题二:取值不判空,直接用会崩

演示代码里展示了正确的取值方式:

// 模拟其他页面读取登录状态constisLogin=GlobalContext.getContext().get<boolean>('isLogin');constname=GlobalContext.getContext().get<string>('userName');constid=GlobalContext.getContext().get<number>('userId');this.addLog(`isLogin:${isLogin}name:${name}userId:${id}`);

这里isLoginnameid都可能是undefined(比如 clear 了或者还没 put),直接name.toUpperCase()就崩了。

正确的防御性写法:

// 先 has 判断if(GlobalContext.getContext().has('userName')){constname=GlobalContext.getContext().get<string>('userName')!;// 这里可以安全使用 name}// 或者用空值合并运算符constname=GlobalContext.getContext().get<string>('userName')??'未登录';constid=GlobalContext.getContext().get<number>('userId')??0;

?? '默认值'是空值合并,当值为undefinednull时使用默认值。

问题三:取出来是 Object,用时要类型断言

get<T>虽然有泛型,但底层存的是Object,取复杂对象时要注意:

// 存对象constobj:UserInfo={name:'若城',age:18,roles:['admin','user']};GlobalContext.getContext().put('userInfo',obj);// 取对象:get<object> 返回的是 object,访问具体属性需要类型断言constinfo=GlobalContext.getContext().get<object>('userInfo');this.addLog(`get("userInfo") →${info?JSON.stringify(info):'undefined'}`);

如果要访问info.name,直接info.name在 ArkTS 里会报类型错误。需要:

constinfo=GlobalContext.getContext().get<UserInfo>('userInfo');if(info){// 这里 info 是 UserInfo 类型,可以访问 .name .agethis.addLog(`用户名:${info.name}`);}

关键点:get<T>里的T用具体的 interface 或 class,不要用object

推荐的封装模式

如果 GlobalContext 用得很频繁,可以进一步封装,把 Key 和类型绑定在一起:

// 模拟登录后存储(演示代码里的完整示例)GlobalContext.getContext().put('isLogin',true);GlobalContext.getContext().put('token','Bearer eyJhbGci.example');GlobalContext.getContext().put('userName','全栈若城');GlobalContext.getContext().put('userId',10086);

可以把这段"登录后存储"逻辑封装成一个函数:

functionsaveLoginState(token:string,userName:string,userId:number):void{constctx=GlobalContext.getContext();ctx.put('isLogin',true);ctx.put('token',token);ctx.put('userName',userName);ctx.put('userId',userId);}functionclearLoginState():void{GlobalContext.getContext().clear();}functiongetToken():string{returnGlobalContext.getContext().get<string>('token')??'';}

这样业务代码里只调用saveLoginStateclearLoginStategetToken,不直接操作 GlobalContext,维护性更好。

退出登录的正确姿势

演示代码里展示了退出登录的完整流程:

// 模拟退出登录 —— clear 全部GlobalContext.getContext().clear();constisLogin=GlobalContext.getContext().get<boolean>('isLogin');this.addLog(`退出后 isLogin:${isLogin}`);// 结果:undefined(说明已清除)

clear()一步到位,所有登录相关的数据全部清除。

但注意:clear()会清除所有 key,包括那些和登录无关的全局配置。如果有些数据不应该在退出登录时清除(比如应用语言设置),那就用remove逐个清除登录相关的 key,而不是clear

// 精准清除,只删登录相关的 keyGlobalContext.getContext().remove('isLogin');GlobalContext.getContext().remove('token');GlobalContext.getContext().remove('userName');GlobalContext.getContext().remove('userId');// 不清除 'appLanguage'、'appTheme' 等配置 key

写在最后

GlobalContext 用好需要注意三点:

  1. Key 统一管理:用常量文件,不要满代码散落魔法字符串
  2. 取值必判空:用??提供默认值,或先has再取
  3. 泛型要具体get<UserInfo>get<object>好用得多

小工具用得规范,大项目才不会变成烂摊子。

http://www.cnnetsun.cn/news/2627467.html

相关文章:

  • MATLAB系统辨识实战:用最小二乘法搞定电机模型参数估计(附完整代码)
  • 在Ubuntu 18.04上搞定Matlab 2021b:从挂载ISO到解决‘桌面配置保存失败’的完整指南
  • 湖北玖晟工业气膜|核心专属优势
  • Arduino Nano通用传感器测试板设计:从原理到实战的硬件开发指南
  • 技术原理篇:GEO(生成式引擎优化)核心技术架构与 AI 收录机制解析
  • 告别Windows!在Ubuntu 22.04上搞定NI-VISA驱动,让你的USB示波器跑起来
  • VirtualBox装Win10后必做的3件事:共享文件夹、拖放文件、剪贴板同步(附增强工具包下载)
  • 【心电图处理】基于MIT-BIH心律失常数据库心电图信号去噪、R峰检测和心率变异性HRV分析Matlab实现
  • 干掉繁琐搬运!企业级AI Agent免费社区版深度评测:中小企业数字化转型的“破局”利器
  • 通过 Taotoken CLI 一键配置团队开发环境中的模型密钥
  • 格式错位=推理失效?DeepSeek RAG流水线中JSON Schema校验缺失导致37%响应解析失败,速查修复清单
  • 使用GD32实现JTAG功能
  • 手把手教你用OSX-KVM项目搞定macOS Monterey安装:从XML配置到驱动优化避坑指南
  • 第05篇|窗口与安全区:AppStorage 如何保存宽高、状态栏和暗色模式
  • 告别虚拟机!在安卓手机上用Termux运行ArchLinux,实测开发环境搭建与避坑指南
  • bean的作用域与生命周期
  • 6Pin数码管驱动和编码器旋钮检测
  • 从Solidworks草图到桌面摆件:我如何用3D打印给自己做了个PLA手机支架(附切片避坑指南)
  • Taotoken用量看板与成本管理功能的实际使用观感
  • 基于ESP32与SCD41传感器的开源智能CO₂监测仪制作全攻略
  • 如何用哔哩下载姬downkyi轻松下载B站视频:从入门到精通完全指南
  • WingData HTB 渗透测试完整攻略
  • 别再自己写扫码了!用uniapp插件Ba-Scanner,5分钟搞定连续扫码和自定义UI
  • 笔记本刚开机就高温?CPU 90℃、风扇狂转、网速消耗殆尽——威胁检测工程师实战排查全过程
  • PointPillars算法避坑指南:从VoxelNet到Apollo实战,聊聊那些容易踩的‘坑’
  • 权重衰减为何放入优化器
  • 什么是OPC(一人公司)?
  • 代码即玩法:非典型游戏开发的英文提示词实践
  • 从 MCP 到 A2A:Agent 项目里“通信协议”到底在解决什么问题?
  • 别再手动排路线了!用Python+遗传算法搞定物流配送VRP(附完整代码)