HarmonyOS 全局状态管理实战:GlobalContext 跨页面数据共享完全指南
文章目录
- 前言
- GlobalContext 是什么
- 写入:put 和 setObject
- 读取:get 和 getObject
- has:检查 Key 是否存在
- remove:移除指定 Key
- clear:清空所有缓存
- 综合演示:模拟登录状态管理
- GlobalContext vs AppStorage:怎么选
- 写在最后
前言
近期发现一款很有意思的HarmonyOS 三方库, 地址 @pura/harmony-utils(V1.4.0) , 作者是"桃花镇童长老", 我这里也是直接通过该作者公布的源码进行案例编写进行,写了到目前写了一部分demo ,感觉确实很有帮助,这里呢也是开始写一个系列的演示demo 供大家参考。如有帮助可以在OpenHarmony中进行下载安装进行使用哦
案例demo导航展示
↓↓↓↓↓↓接下来言归正传 ↓↓↓↓
写 HarmonyOS App,很快就会遇到一个问题:登录成功后,token 存在哪,其他页面怎么拿?
路由传参只能传一次,AppStorage有绑定 UI 的额外开销,很多时候你就想要个简单的"全局 HashMap"——存进去,随时取,谁都能用。
GlobalContext就是这个东西。
GlobalContext 是什么
GlobalContext是一个应用级别的单例 Key-Value 缓存,本质上就是一个Map<string, Object>。
它的特点:
- 单例:整个应用只有一个实例,所有页面共享
- 类型安全:支持泛型取值,取出来的类型可以直接用
- 轻量:没有响应式、没有 UI 绑定,就是纯粹的键值存储
演示代码里的描述:
Column({space:4}){Text('GlobalContext 是应用全局单例 Key-Value 缓存').fontSize(13).fontColor('#555')Text('支持跨页面、跨组件传递任意 Object 数据').fontSize(12).fontColor('#888')}写入:put 和 setObject
// put:写入任意类型GlobalContext.getContext().put(this.inputKey,this.inputValue);this.addLog(`put("${this.inputKey}", "${this.inputValue}")`);// setObject:功能一样,名字不同GlobalContext.getContext().setObject(this.inputKey,this.inputValue);this.addLog(`setObject("${this.inputKey}", "${this.inputValue}")`);put和setObject功能完全等同,语义略有差别,按习惯选一个用就好。
写入数字类型:
GlobalContext.getContext().put('timestamp',Date.now());this.addLog(`put("timestamp",${Date.now()})`);写入对象类型:
// 先定义 interfaceinterfaceUserInfo{name:string;age:number;roles:string[];}// 再写入constobj:UserInfo={name:'若城',age:18,roles:['admin','user']};GlobalContext.getContext().put('userInfo',obj);this.addLog(`put("userInfo",${JSON.stringify(obj)})`);GlobalContext 的值类型是Object,所以可以存任意类型。
读取:get 和 getObject
// get<T>:泛型取值,返回 T 类型constval=GlobalContext.getContext().get<string>(this.inputKey);this.getResult=val!==undefined?String(val):'(undefined)';this.addLog(`get("${this.inputKey}") →${this.getResult}`);// getObject:不带泛型,返回 Objectconstval=GlobalContext.getContext().getObject(this.inputKey);this.addLog(`getObject("${this.inputKey}") →${val!==undefined?String(val):'undefined'}`);get<T>带泛型更推荐,因为取出来的值直接是对应类型,不需要强转。
取数字:
constts=GlobalContext.getContext().get<number>('timestamp');this.addLog(`get<number>("timestamp") →${ts}`);取对象:
constinfo=GlobalContext.getContext().get<object>('userInfo');this.addLog(`get("userInfo") →${info?JSON.stringify(info):'undefined'}`);注意:如果 key 不存在,get返回undefined,使用前要判断是否 undefined,不然直接访问属性会空指针崩溃。
has:检查 Key 是否存在
constresult=GlobalContext.getContext().has(this.inputKey);this.hasResult=result?'存在':'不存在';this.addLog(`has("${this.inputKey}") →${result}`);// 检查不存在的 keyconstr=GlobalContext.getContext().has('notExistKey');this.addLog(`has("notExistKey") →${r}`);// 结果:false在读取数据前,用has判断 key 是否存在是个好习惯:
if(GlobalContext.getContext().has('token')){consttoken=GlobalContext.getContext().get<string>('token');// 安全使用 token}remove:移除指定 Key
// 移除单个 keyGlobalContext.getContext().remove(this.inputKey);this.addLog(`remove("${this.inputKey}") 已移除`);// 移除后验证GlobalContext.getContext().remove(this.inputKey);constr=GlobalContext.getContext().has(this.inputKey);this.addLog(`remove后 has("${this.inputKey}") →${r}`);// 结果:falseclear:清空所有缓存
GlobalContext.getContext().clear();this.addLog('clear() 已清空所有缓存');// 清空后验证GlobalContext.getContext().clear();constr1=GlobalContext.getContext().has(this.inputKey);constr2=GlobalContext.getContext().has('userInfo');this.addLog(`clear后 has("${this.inputKey}") →${r1}`);this.addLog(`clear后 has("userInfo") →${r2}`);// 结果都是 falseclear适合在退出登录时调用,一次性清除所有用户相关的全局状态。
综合演示:模拟登录状态管理
演示代码里有一段完整的登录状态模拟,非常实用:
模拟登录后存储数据:
GlobalContext.getContext().put('isLogin',true);GlobalContext.getContext().put('token','Bearer eyJhbGci.example');GlobalContext.getContext().put('userName','全栈若城');GlobalContext.getContext().put('userId',10086);this.addLog('已存储登录信息: isLogin/token/userName/userId');模拟其他页面读取登录状态:
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}`);模拟退出登录:
GlobalContext.getContext().clear();constisLogin=GlobalContext.getContext().get<boolean>('isLogin');this.addLog(`退出后 isLogin:${isLogin}`);// 结果:undefined这三步代码展示了 GlobalContext 的完整生命周期:登录存数据、使用时读数据、退出时清数据。
GlobalContext vs AppStorage:怎么选
| 特性 | GlobalContext | AppStorage |
|---|---|---|
| 响应式 | ❌ | ✅ |
| UI 双向绑定 | ❌ | ✅ |
| 轻量级 | ✅ | ✅ |
| 适合存非 UI 数据 | ✅ | 不推荐 |
| 适合存 token、userId | ✅ | 一般用全局变量 |
简单原则:需要 UI 自动更新的数据用@State/AppStorage,不需要 UI 响应的全局数据(token、配置、用户信息)用GlobalContext。
写在最后
GlobalContext 的 API 很简单,就四组:
put/setObject:写数据get<T>/getObject:读数据,推荐用泛型版has:判断 key 是否存在remove/clear:删除单个或全部
适合存的东西:token、用户 ID、全局配置、应用上下文对象。不适合存的:需要 UI 响应的状态数据(那个用@State或AppStorage)。
