鸿蒙状态管理-AppStorage-PersistentStorage-首选项等

111 阅读7分钟

状态管理的种类

ArtTS提供了好几种状态用来帮助我们管理我们的全局数据

  1. LocalStorage-UIAbility状态(内存- 注意:和前端的区分开,它非持久化,非全应用)
  2. AppStorage- 全局应用内状态-多UIAbility共享-(内存-非持久化-退出应用同样消失)
  3. PersistentStorage-持久化的全局应用内状态(写入磁盘-持久化状态-退出应用 数据同样存在)
  4. Preferences 首选项- 写入磁盘
  5. 关系型数据库 - 写入磁盘
  6. 端云数据库
  7. 接口调用-云端数据(服务器数据)

状态管理对比

特性LocalStorageAppStoragePersistentStoragePreferences首选项
作用范围页面级或 UIAbility 内应用全局应用全局 + 持久化全局+持久化
存储位置内存内存磁盘内存或磁盘
生命周期页面销毁时清除应用退出时清除长期保留(除非删除/卸载)不调用flush在内存,调用后写入磁盘
数据同步机制单向/双向组件绑定单向/双向全局绑定持久化的 AppStorageget和put方法取值和修改值
典型应用场景页面内状态共享全局状态管理需长期保存的关键数据保存用户的个性化设置

UIAbility内状态-LocalStorage(我不常用)

LocalStorage 是页面级的UI状态存储,通过 @Entry 装饰器接收的参数可以在页面内共享同一个 LocalStorage 实例。 LocalStorage 也可以在 UIAbility 内,页面间共享状态。

用法

  1. 创建 LocalStorage 实例:const storage = new LocalStorage({ key: value })
  2. 单向 @LocalStorageProp('user') 组件内可变
  3. 双向 @LocalStorageLink('user') 全局均可变

应用状态-AppStorage(重要)

LocalStorage是针对UIAbility的状态共享- 一个UIAbility有个页面

一个应用可能有若干个UIAbility

概述

AppStorage是在应用启动的时候会被创建的单例。它的目的是为了提供应用状态数据的中心存储,这些状态数据在应用级别都是可访问的。AppStorage将在应用运行过程保留其属性。属性通过唯一的键字符串值访问。

AppStorage可以和UI组件同步,且可以在应用业务逻辑中被访问。

AppStorage支持应用的主线程内多个UIAbility实例间的状态共享。

AppStorage中的属性可以被双向同步,数据可以是存在于本地或远程设备上,并具有不同的功能,比如数据持久化(详见PersistentStorage)。这些数据是通过业务逻辑中实现,与UI解耦,如果希望这些数据在UI中使用,需要用到@StorageProp@StorageLink

AppStorage 是应用全局的UI状态存储,是和应用的进程绑定的,由UI框架在应用程序启动时创建,为应用程序UI状态属性提供中央存储。-注意它也是内存数据,不会写入磁盘

第一种用法-使用UI修饰符

  1. 如果是初始化使用 AppStorage.setOrCreate(key,value)
  2. 单向 @StorageProp('user') 组件内可变
  3. 双向 @StorageLink('user') 全局均可变

第二种用法 使用API方法

  1. AppStorage.get<ValueType>(key) 获取数据
  2. AppStorage.set<ValueType>(key,value) 覆盖数据

AppStorage.setOrCreate("", T) // 创建或者设置某个字段的属性

AppStorage.get("") // 获取的全局状态类型

如果遇到获取数据的类型为空,可以用if判断,也可以用非空断言来解决

StorageLink . - 直接修改-自动同步到全局状态

StorageProp- 可以改,只会在当前组件生效,只是改的全局状态的副本,不会对全局状态产生影响

状态持久化-PersistentStorage

前面讲的所有状态均为内存状态,也就是应用退出便消失,所以如果我们想持久化的保留一些数据,应该使用

PersistentStorage

注意:

UI和业务逻辑不直接访问 PersistentStorage 中的属性,所有属性访问都是对 AppStorage 的访问,AppStorage 中的更改会自动同步到 PersistentStorage

也就是,我们和之前访问AppStorage是一样的,只不过需要提前使用PersistentStorage来声明

PersistentStorage 将选定的 AppStorage 属性保留在设备磁盘上。

  1. 支持:number, string, boolean, enum 等简单类型;
  2. 如果:要支持对象类型,可以转换成json字符串
  3. 持久化变量最好是小于2kb的数据,如果开发者需要存储大量的数据,建议使用数据库api。

用法:

PersistentStorage.PersistProp('属性名', 值)

注意: 如果用了持久化, 那么AppStorage读取出来的对象实际上是PersistentStorage存储的json字符串

如果没用持久化 。那么读取出来的对象就是AppStorage对象

只要初始化了数据,我们以后使用AppStorage就可以读取和设置,它会自动同步到我们的磁盘上

目前不支持复杂对象的持久化,如果你需要存储,你需要把它序列化成功字符串

  1. 测试:需要在真机或模拟器调试

限制条件

PersistentStorage允许的类型和值有:

  1. number, string, boolean, enum 等简单类型。
  2. 可以被JSON.stringify()和JSON.parse()重构的对象,但是对象中的成员方法不支持持久化。
  3. API 12 及以上版本支持 Date, Map, Set 等内置类型。

PersistentStorage不允许的类型和值有:

  1. 不支持嵌套对象(对象数组,对象的属性是对象等) 。因为目前框架无法检测 AppStorage 中嵌套对象(包括数组)值的变化,所以无法写回到 PersistentStorage 中。

持久化数据是一个相对缓慢的操作,应用程序应避免以下情况:

  1. 持久化大型数据集。
  2. 持久化经常变化的变量。

PersistentStorage的持久化变量最好是小于2kb的数据,不要大量的数据持久化,因为PersistentStorage写入磁盘的操作是同步的,大量的数据本地化读写会同步在UI线程中执行,影响UI渲染性能。如果开发者需要存储大量的数据,建议使用数据库api。

PersistentStorage只能在UI页面内使用,否则将无法持久化数据。

所以最早能初始化PersistentStorage的声明周期就是windowStage.loadContent()

import { TOKEN_KEY, USER_INFO } from '../constants'

import { UserInfoClass } from '../viewmodels'

// 封装存储

export class UserSetting {

// 持久化存储

initSetting() {

PersistentStorage.persistProp(USER_INFO, {}) // 用户信息

PersistentStorage.persistProp(TOKEN_KEY, '') // token

// ... 有就在加

}

// 用户信息 -------------------------------------

// 获取

getSetting(): UserInfoClass{

return AppStorage.get(USER_INFO) as UserInfoClass

}

// 设置

setSetting(user: UserInfoClass) {

AppStorage.set(USER_INFO, user)

}

// token --------------------------------------

// 获取token

getToken(): string {

return AppStorage.get(TOKEN_KEY) as string

}

// 设置token

setToken(token: string) {

AppStorage.set(TOKEN_KEY, token)

}

// ------ 有就在加

}

// 导出

export const userSetting = new UserSetting()

Preferences 首选项

基本概念:

  1. 创建首选项-仓库的概念- 应用可以有N个仓库,一个仓库中可以有N个key
  2. 用户首选项为应用提供Key-Value键值型的数据处理能力,支持应用持久化轻量级数据,并对其修改和查询。
  3. 数据存储形式为键值对,键的类型为字符串型,值的存储数据类型包括数字型、字符型、布尔型以及这3种类型的数组类型。

条件限制:

  1. Key键为string类型,要求非空且长度不超过1024个字节。
  2. 如果Value值为string类型,请使用UTF-8编码格式,可以为空,不为空时长度不超过16 Mb个字节。
  3. 内存会随着存储数据量的增大而增大,所以存储的数据量应该是轻量级的,建议存储的数据不超过一万条,否则会在内存方面产生较大的开销。
  4. 获取首选项实例

const dataPreferences = preferences.getPreferencesSync(context, { name: '' });

  1. 写入|修改,并持久化

dataPreferences.putSync('startup', 'auto');

dataPreferences.flush()

  1. 读取

dataPreferences.getSync('startup', 默认值 ) // 获取不到的时候,用默认值

  1. 删除,并持久化

dataPreferences.deleteSync('startup');

dataPreferences.flush()

  1. 删除首选项实例

preferences.deletePreferences(context, options)