状态管理的种类
ArtTS提供了好几种状态用来帮助我们管理我们的全局数据
- LocalStorage-UIAbility状态(内存- 注意:和前端的区分开,它非持久化,非全应用)
- AppStorage- 全局应用内状态-多UIAbility共享-(内存-非持久化-退出应用同样消失)
- PersistentStorage-持久化的全局应用内状态(写入磁盘-持久化状态-退出应用 数据同样存在)
- Preferences首选项- 写入磁盘
- 关系型数据库 - 写入磁盘
- 端云数据库
- 接口调用-云端数据(服务器数据)
API版本
LocalStorage API 9+
AppStorage API 11之后元服务也可使用
PersistentStorage API 12+ 支持的用法更全面
Preferences首选项 支持所有
状态管理对比
特性 | Preferences首选项 | |||
作用范围 | 页面级或 UIAbility 内 | 应用全局 | 应用全局 + 持久化 | 全局+持久化 |
存储位置 | 内存 | 内存 | 磁盘 | 内存或磁盘 |
生命周期 | 页面销毁时清除 | 应用退出时清除 | 长期保留(除非删除/卸载) | 不调用flush在内存,调用后写入磁盘 |
数据同步机制 | 单向/双向组件绑定 | 单向/双向全局绑定 | 持久化的 AppStorage | get和put方法取值和修改值 |
典型应用场景 | 页面内状态共享 | 全局状态管理 | 需长期保存的关键数据 | 保存用户的个性化设置 |
UIAbility内状态-LocalStorage(我不常用)
LocalStorage
是页面级的UI状态存储,通过 @Entry
装饰器接收的参数可以在页面内共享同一个 LocalStorage
实例。 LocalStorage
也可以在 UIAbility
内,页面间共享状态。
用法
- 创建
LocalStorage
实例:const storage = new LocalStorage({ key: value })
- 单向
@LocalStorageProp('user')
组件内可变 - 双向
@LocalStorageLink('user')
全局均可变
应用状态-AppStorage(重要)
LocalStorage是针对UIAbility的状态共享- 一个UIAbility有个页面
一个应用可能有若干个UIAbility
概述
AppStorage是在应用启动的时候会被创建的单例。它的目的是为了提供应用状态数据的中心存储,这些状态数据在应用级别都是可访问的。AppStorage将在应用运行过程保留其属性。属性通过唯一的键字符串值访问。
AppStorage可以和UI组件同步,且可以在应用业务逻辑中被访问。
AppStorage支持应用的主线程内多个UIAbility实例间的状态共享。
AppStorage中的属性可以被双向同步,数据可以是存在于本地或远程设备上,并具有不同的功能,比如数据持久化(详见PersistentStorage)。这些数据是通过业务逻辑中实现,与UI解耦,如果希望这些数据在UI中使用,需要用到@StorageProp和@StorageLink。
AppStorage
是应用全局的UI状态存储,是和应用的进程绑定的,由UI框架在应用程序启动时创建,为应用程序UI状态属性提供中央存储。-注意它也是内存数据,不会写入磁盘
第一种用法-使用UI修饰符
- 如果是初始化使用
AppStorage.setOrCreate(key,value)
- 单向
@StorageProp('user')
组件内可变 - 双向
@StorageLink('user')
全局均可变
第二种用法 使用API方法
AppStorage.get<ValueType>(key)
获取数据AppStorage.set<ValueType>(key,value)
覆盖数据
AppStorage.setOrCreate<T>("", T) // 创建或者设置某个字段的属性
AppStorage.get<T>("") // 获取的全局状态类型
如果遇到获取数据的类型为空,可以用if判断,也可以用非空断言来解决
StorageLink . - 直接修改-自动同步到全局状态
StorageProp- 可以改,只会在当前组件生效,只是改的全局状态的副本,不会对全局状态产生影响
状态持久化-PersistentStorage
前面讲的所有状态均为内存状态,也就是应用退出便消失,所以如果我们想持久化的保留一些数据,应该使用
PersistentStorage
。
注意:
UI和业务逻辑不直接访问 PersistentStorage
中的属性,所有属性访问都是对 AppStorage
的访问,AppStorage
中的更改会自动同步到 PersistentStorage
。
也就是,我们和之前访问AppStorage是一样的,只不过需要提前使用PersistentStorage来声明
PersistentStorage
将选定的 AppStorage
属性保留在设备磁盘上。
- 支持:number, string, boolean, enum 等简单类型;
- 如果:要支持对象类型,可以转换成json字符串
- 持久化变量最好是小于2kb的数据,如果开发者需要存储大量的数据,建议使用数据库api。
用法:
PersistentStorage.PersistProp('属性名', 值)
注意: 如果用了持久化, 那么AppStorage读取出来的对象实际上是PersistentStorage存储的json字符串
如果没用持久化 。那么读取出来的对象就是AppStorage对象
只要初始化了数据,我们以后使用AppStorage就可以读取和设置,它会自动同步到我们的磁盘上
目前不支持复杂对象的持久化,如果你需要存储,你需要把它序列化成功字符串
- 测试:需要在真机或模拟器调试
限制条件
PersistentStorage允许的类型和值有:
- number, string, boolean, enum 等简单类型。
- 可以被JSON.stringify()和JSON.parse()重构的对象,但是对象中的成员方法不支持持久化。
- API 12 及以上版本支持 Date, Map, Set 等内置类型。
PersistentStorage不允许的类型和值有:
- 不支持嵌套对象(对象数组,对象的属性是对象等)。因为目前框架无法检测 AppStorage 中嵌套对象(包括数组)值的变化,所以无法写回到 PersistentStorage 中。
持久化数据是一个相对缓慢的操作,应用程序应避免以下情况:
- 持久化大型数据集。
- 持久化经常变化的变量。
PersistentStorage的持久化变量最好是小于2kb的数据,不要大量的数据持久化,因为PersistentStorage写入磁盘的操作是同步的,大量的数据本地化读写会同步在UI线程中执行,影响UI渲染性能。如果开发者需要存储大量的数据,建议使用数据库api。
PersistentStorage只能在UI页面内使用,否则将无法持久化数据。
注意:要在使用AppStorage之前,UI实例初始化成功后,调用PersistentStorage进行初始化,这样才能将AppStorage中key对应的属性持久化到文件中,我是直接在加载页面的回调中调用的。
用PersistentStorage持久化存储token和用户信息的例子
import { TOKEN_KEY, USER_INFO } from '../constants'
import { UserInfoClass } from '../viewmodels'
// 封装存储
export class UserSetting {
// 持久化存储
initSetting() {
PersistentStorage.persistProp<UserInfoClass>(USER_INFO, {}) // 用户信息
PersistentStorage.persistProp<string>(TOKEN_KEY, '') // token
// ... 有就在加
}
// 用户信息 -------------------------------------
// 获取
getSetting(): UserInfoClass{
return AppStorage.get<UserInfoClass>(USER_INFO) as UserInfoClass
}
// 设置
setSetting(user: UserInfoClass) {
AppStorage.set<UserInfoClass>(USER_INFO, user)
}
// token --------------------------------------
// 获取token
getToken(): string {
return AppStorage.get<string>(TOKEN_KEY) as string
}
// 设置token
setToken(token: string) {
AppStorage.set<string>(TOKEN_KEY, token)
}
// ------ 有就在加
}
// 导出
export const userSetting = new UserSetting()
Preferences 首选项
基本概念:
- 创建首选项-仓库的概念- 应用可以有N个仓库,一个仓库中可以有N个key
- 用户首选项为应用提供Key-Value键值型的数据处理能力,支持应用持久化轻量级数据,并对其修改和查询。
- 数据存储形式为键值对,键的类型为字符串型,值的存储数据类型包括数字型、字符型、布尔型以及这3种类型的数组类型。
条件限制:
- Key键为string类型,要求非空且长度不超过1024个字节。
- 如果Value值为string类型,请使用UTF-8编码格式,可以为空,不为空时长度不超过16 Mb个字节。
- 内存会随着存储数据量的增大而增大,所以存储的数据量应该是轻量级的,建议存储的数据不超过一万条,否则会在内存方面产生较大的开销。
- 获取首选项实例
const dataPreferences = preferences.getPreferencesSync(context, { name: '' });
- 写入|修改,并持久化
dataPreferences.putSync('startup', 'auto');
dataPreferences.flush()
- 读取
dataPreferences.getSync('startup', 默认值 ) // 获取不到的时候,用默认值
- 删除,并持久化
dataPreferences.deleteSync('startup');
dataPreferences.flush()
- 删除首选项实例
preferences.deletePreferences(context, options)