HarmonyOS7 AppStorage 和 PersistentStorage 到底该选谁?全局状态别再用乱
文章目录前言AppStorage内存级的全局仓库PersistentStorage能活过重启的存储两者配合的最佳实践实战登录态 主题色 语言的全局管理几个实用建议最后聊两句前言做鸿蒙开发绕不开一个问题用户登录了首页要显示昵称我的页面要显示头像设置页要展示会员等级。多个页面共享同一份数据怎么搞State和Prop搞不定跨组件通信这时候就该AppStorage出场了。但如果用户杀了应用再打开你还想保留这些数据呢那得加上PersistentStorage。今天把这两个东西掰清楚了讲再给个实际项目中的搭配方案。AppStorage内存级的全局仓库AppStorage是个单例的键值对存储整个应用生命周期内有效。你往里塞个值任何组件都能读出来。核心 API 很简单// 写入AppStorage.setOrCreatestring(userName,张三)AppStorage.setOrCreatenumber(userId,10086)// 读取letnameAppStorage.getstring(userName)// 张三// 删除AppStorage.delete(userName)// 检查是否存在AppStorage.has(userName)// false在组件里用起来更顺手用StorageProp和StorageLinkComponentstruct UserProfile{// 只读——AppStorage 变了UI 会刷新但改这个变量不会写回StorageProp(userName)userName:string// 双向——改了这个变量AppStorage 里的值也变StorageLink(themeColor)themeColor:string#3498dbbuild(){Column(){Text(欢迎回来${this.userName}).fontSize(18)Button(切换主题色).onClick((){this.themeColorthis.themeColor#3498db?#e74c3c:#3498db}).backgroundColor(this.themeColor)}}}StorageProp是单向的组件读 AppStorage 的值但改本地变量不会影响全局。StorageLink是双向的改一头另一头跟着动。AppStorage 的局限它是纯内存的。应用被系统杀掉、用户手动退出数据就没了。下次打开又是白纸一张。PersistentStorage能活过重启的存储PersistentStorage解决的就是持久化问题。它把数据写到磁盘上应用重启后自动恢复。用法也不复杂// 在应用启动时调用通常在 UIAbility 的 onCreate 里PersistentStorage.persistPropstring(userName,)PersistentStorage.persistPropstring(themeColor,#3498db)PersistentStorage.persistPropstring(language,zh-CN)persistProp的意思是如果磁盘上有这个 key 的值就恢复到 AppStorage 里如果没有就用给的默认值。之后在组件里照常用StorageProp或StorageLink读写完全不用关心底层是内存还是磁盘。PersistentStorage自动在后台同步。两者配合的最佳实践实际项目中不是所有数据都需要持久化。我一般这么分数据类型存储方式例子需要持久化的设置PersistentStorageStorageLink主题色、语言、字体大小临时全局状态AppStorageStorageLink登录态、当前页面索引敏感信息不存这里Token 走安全存储关键原则PersistentStorage 负责恢复现场AppStorage 负责运行时共享。实战登录态 主题色 语言的全局管理先看应用入口在UIAbility里初始化持久化存储// entry/src/main/ets/entryability/EntryAbility.etsimportUIAbilityfromohos.app.ability.UIAbilityexportdefaultclassEntryAbilityextendsUIAbility{onCreate(want:Want,launchParam:AbilityConstant.LaunchParam):void{// 持久化这些需要跨重启保留的设置PersistentStorage.persistPropstring(themeColor,#3498db)PersistentStorage.persistPropstring(language,zh-CN)PersistentStorage.persistPropnumber(fontSize,16)PersistentStorage.persistPropboolean(isDarkMode,false)// 登录态不需要持久化安全考虑AppStorage.setOrCreateboolean(isLoggedIn,false)AppStorage.setOrCreatestring(userName,)}}注意Token、密码这类敏感信息不要往 PersistentStorage 里塞。它底层用的是 Preferences数据是明文存储的。敏感信息应该走ohos.security.keystore或业务侧加密后存储。然后搞一个设置页面Componentstruct SettingsPage{StorageLink(themeColor)themeColor:string#3498dbStorageLink(language)language:stringzh-CNStorageLink(fontSize)fontSize:number16StorageLink(isDarkMode)isDarkMode:booleanfalseStorageLink(isLoggedIn)isLoggedIn:booleanfalseStorageLink(userName)userName:stringbuild(){Column({space:20}){Text(设置).fontSize(22).fontWeight(FontWeight.Bold)// 主题色选择Row(){Text(主题色).fontSize(this.fontSize)Blank()Row({space:12}){Circle({width:30,height:30}).fill(#3498db).onClick((){this.themeColor#3498db})Circle({width:30,height:30}).fill(#e74c3c).onClick((){this.themeColor#e74c3c})Circle({width:30,height:30}).fill(#2ecc71).onClick((){this.themeColor#2ecc71})}}.width(100%).padding(12)// 语言选择Row(){Text(语言).fontSize(this.fontSize)Blank()Text(this.languagezh-CN?中文:English).fontSize(this.fontSize).onClick((){this.languagethis.languagezh-CN?en-US:zh-CN})}.width(100%).padding(12)// 字体大小Row(){Text(字体大小).fontSize(this.fontSize)Blank()Slider({value:this.fontSize,min:12,max:24,step:1}).width(150).onChange((value:number){this.fontSizevalue})Text(${this.fontSize}).width(30)}.width(100%).padding(12)// 暗色模式Row(){Text(暗色模式).fontSize(this.fontSize)Blank()Toggle({type:ToggleType.Switch,isOn:this.isDarkMode}).onChange((isOn:boolean){this.isDarkModeisOn})}.width(100%).padding(12)// 模拟登录/登出Button(this.isLoggedIn?退出登录:登录).backgroundColor(this.isLoggedIn?#999:this.themeColor).onClick((){if(this.isLoggedIn){this.isLoggedInfalsethis.userName}else{this.isLoggedIntruethis.userName张三}})}.padding(20)}}首页读取这些设置Componentstruct HomePage{StorageProp(userName)userName:stringStorageProp(isLoggedIn)isLoggedIn:booleanfalseStorageProp(themeColor)themeColor:string#3498dbStorageProp(fontSize)fontSize:number16build(){Column(){Text(this.isLoggedIn?Hi,${this.userName}:请先登录).fontSize(this.fontSize4).fontColor(this.themeColor)Text(这里是首页内容区域).fontSize(this.fontSize).margin({top:20})}.width(100%).padding(20)}}用户在设置页改了主题色首页的标题颜色立刻跟着变。杀应用重启主题色还是上次选的那个但登录状态没了——因为登录态走的是AppStorage不持久化。几个实用建议不要在 PersistentStorage 里存大对象。它底层用的 Preferences 有大小限制存个字符串、数字、布尔值没问题塞个几百 KB 的 JSON 就不合适了。大数据走关系型数据库或文件。初始化的时机要早。PersistentStorage.persistProp要在任何组件读取之前调用最靠谱的地方就是UIAbility.onCreate。放在页面组件的aboutToAppear里可能会来不及。命名要规范。key 都是全局的不同模块之间容易撞名。我建议加前缀比如settings.themeColor、user.name。最后聊两句AppStorage和PersistentStorage这对搭档用起来其实挺简单的。核心就是分清楚哪些数据要持久化、哪些不用。真正让人纠结的是什么时候该用全局状态。我的原则是能不用就不用。如果数据只在一个组件树里流转老老实实用StatePropLink往下传。全局状态是个诱惑用多了会让代码变得难追踪。等数据真正需要跨页面、跨模块共享了再把AppStorage请出来。

相关新闻