HarmonyOS应用级别的状态管理

应用状态管理

概念

  1. AppStorage:应用全局UI存储(范围是整个应用),是和应用进程绑定,由UI框架在应用程序启动时创建。为应用程序UI状态提供中央存储

  2. AppStorage是应用级的全局共享,相当于整个应用的 ‘中枢’ ,持久化数据PersistentStorage是通过AppStorage进行中转,才能与UI进行交互

  3. 方法

    •   // AppStorage
        // AppStorage.ref('name')	查找某个name是否在AppStorage中存在,如果存在则获得其数据的引用,否则返回undefined
        // AppStorage.setAndRef	 如果能找到,则与ref相同,如果找不到,则创建之后再去寻找
        // AppStorage.link('name')	与ref大致相同,获得数据与原数据形成双向绑定,与ref区别在于link会同时订阅目标数据【不可删除】,但是ref不会
        // AppStorage.delete	删除对应名称的数据,前提是该数据没有被订阅
        // AppStorage.setAndLink	如果能够找到,则与link相同,如果找不到,则创建之后再去寻找
        // AppStorage.prop	获得数据与原数据形成单向绑定
        // AppStorage.setAndProp 如果能够找到,则与prop相同,如果找不到,则创建之后再去寻找
        // AppStorage.has	判断某个数据是否存在,返回boolean
        // AppStorage.get	获取某个数据,如果不不存在返回undefined
        // AppStorage.set	设置对应属性的值。修改,如果新值与旧值相同,则不做任何操作,也不会通知UI更新
        // AppStorage.setOrCreate	如果不存在,则创建。如果存在则进行数据更新,如果新值与旧值相同,则不做任何操作,也不会通知UI更新
        // AppStorage.keys【获取键】
        // AppStorage.clear【清空,前提是没有任意一组数据被订阅】
        // AppStorage.size【获取数据数量】
      
  4. AppStorage可以与UI组件进行双向同步,借助与@StorageProp和@StorageLink实现

    •   AppStorage.setOrCreate('age', 10)
        
        @Entry
        @Component
        struct Test_02 {
          @State message: string = 'Hello World';
          @StorageLink('age') age: number = 10
        
          build() {
            Column() {
        
            }
            .height('100%')
            .width('100%')
          }
        }
      

装饰器

@StorageProp

  • 装饰器参数key常量字符串,必填
  • 允许装饰器的变量类型:与@Stage相同,string,number,boolean,Object,class,enum以及这些类型的数组
  • 同步:单向同步,组件本地的修改是允许的,但是不会同步回AppStorage中,AppStorage给定的属性一旦发生改变,会覆盖本地的修改
  • 初始化:必须指定,如果给定的AppStorage实例中不存在属性,那么使用本地初始化的值,并且存入AppStorage中
  • 不允许从父节点进行初始化
  • 可以初始化的节点:@State,@Link,@Prop,@Provide

@StorageLink

  • 装饰器参数key常量字符串,必填
  • 允许装饰器的变量类型:与@Stage相同,string,number,boolean,Object,class,enum以及这些类型的数组
  • 同步类型:双向同步,从AppStorage的对应属性到自定义组件,从自定义组件到AppStorage对应属性
  • 不允许从父节点进行初始化
  • 可以初始化的节点:@State,@Link,@Prop,@Provide
  • ps
    • 不建议借助@StorageLink的双向同步机制实现事件通知
    • 不建议开发者使用@StorageLink和AppStorage的双向同步机制来实现事件通知因为AppStorage中的变量可能绑定在多个不同的页面组件中,但事件通知不一定需要通知这些组件,并且当这些@StorageLink装饰的变量在UI中使用,会触发UI更新,带来不必要的性能影响
    • 需要数据通知更新,将数据取出来使用

观察变化

  • 当装饰的类型为boolean,string,number,可以观察到其变化
  • 如果是class或者Object,可以观察到对象整体赋值,或者对象属性的变化
  • 当装饰的对象是array时,可以观察到数组的添加,删除,更新数组单元的变化

PersistentStorage

  • PersistentStorage 持久化存储UI状态

  • AppStorage是运行时的内存,一旦应用退出再次启动之后,数据就会被初始化,保存选定的结果是应用开发中必要的需求,这就需要用到PersistentStorage

  • PersistentStorage是应用程序中可选单例对象【可直接调用】,此对象的作用是持久化存储选定AppStorage属性,确保这些属性在应用程序重新启动时的值与应用关闭时的值相同 【类似于自动存档】

  • PersistentStorage 将选定的AppStorage属性确保在设备磁盘上,应用程序通过API,以决定哪些AppStorage属性应借助PersistentStorage持久化。

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

  • 应用开发通常通过AppStorage访问PersistentStorage做持久化

  • 限制条件

    1. 支持存储类型
    - number,string,boolean,enum,可以被JSON.stringify( ) 和 JSON.parse ( ) 重构的对象,但是对象中的成员方法不支持持久化
    
    1. 不允许的类型和值
    - **不支持嵌套对象**(对象数组,对象的属性是对象),因为目前的框架**无法检查AppStorage中嵌套对象(包括数组)值变化,所以无法写回到PersistentStorage**
    - 持久化大型数据集
    - 持久化经常变化的变量
    
    1. PersistentStorage的持久化变量最好小于2KB,不要大量的数据持久化,因为该对象写入磁盘操作同步,大量的数据本地化读写会同步在UI线程执行,影响UI渲染性能,如果需要存储大量数据,建议使用数据库API
    2. PersistentStorage和UI实例相关联,持久化操作需要再UI实例初始化,早于该时期会导致持久化失败【等UI出现才持久化,在onWindowStageCreate中的windowStage.loadContent之后进行操作
PersistentStorage.persistProp('sex', 10)
let num: number | undefined = AppStorage.get<number>('sex')

@Entry
@Component
struct Test_page01 {
  @State message: string = 'Hello World';
  @StorageLink('sex') storageLink: number = 1

  build() {
    Column() {

      Text(`${this.storageLink}`)
        .onClick(() => {
          this.storageLink++
        })

    }
    .width('100%')
    .height('100%')
  }
}

持久化

PersistentStorage.persistProp('sex', 10);
if(AppStorage.get('sex') as number > 30){
  //如果sex的值超过了30,设置为30
  AppStorage.setOrCreate('sex',30)
}
AppStorage.get<number>('sex')
调用persistProp初始化PersistentStorage
新应用安装后
	1:首先查询在PersistentStorage,本地文件是否存在对应属性字段('sex'),查询结果为不存在,因为是第一次安装
	2:接着查询对应属性字段('sex')在AppStorage中是否存在,依旧不存在
	3:在AppStorage中创建名为sex的number类型属性,属性初始值定位默认值为10
	4:PersistentStorage将属性'sex'和值写入磁盘,AppStorage中的'sex'对应的值和后续的改变将被持久化
	5:在自定义组件中创建状态变量@StorageLink('sex'),和AppStorage中的sex双向绑定,在创建的过程会去AppStorage中查找,成功找到,所以其值为在AppStorage中查找到的10

触发点击事件
	1:状态变量发生变更,触发UI更新
	2:与AppStorage形成双向绑定,所以改变会同步回AppStoage,AppStorage中的'sex'属性的改变将同步所有绑定该'sex'的单双向变量,因为'sex'对应的属性已经被持久化,所有AppStorage的改变会触发PersistentStorage将新的改变写入本地磁盘
	
后续启动应用(非首次)
	1:执行PersistentStorage.persistProp('sex',10),首先PersistentStorage本地查询'sex'成功查询
	2:将PersistentStorage查询到的值写入AppStorage【!!!】
	3:在自定义组件中,@StorageLink绑定的'sex'为PersistentStorage写入到AppStorage中的值即为上一次退出应用存入的值
	
  在PersistentStorage之前访问AppStorage中的属性:
  	1:该行为为反例,在调用PersistentStorage.persistProp('sex',10)或者在persistProp之前使用AppStorage中属性是错误的,因为这样的调用顺序会丢失上一次应用程序的属性的值
  	2:应用在非首次创建时,先执行AppStorage.setOrCreate('sex',30)属性'sex'在AppStorage中创建,其类型为number,其设置的值为30,'sex'是持久化属性,所以会被写入到PersistentStorage磁盘中,PersistentStorage存储上次退出应用的值会直接丢失,紧接着执行PersistentStorage.persistProp('sex',10),在AppStorage中查找到了sex字段,值为30
  	3:开发者可以先判断是否需要覆盖上一次保存的值,如果需要覆盖,在调用AppStorage接口,如果不覆盖,那么不需要
  	

你可能感兴趣的:(harmonyos,华为,ui)