鸿蒙UI开发快速入门 —— part09: 应用级状态管理LocalStorage & AppStorage

1、说在前面的话

前面几个章节中介绍的装饰器(@State、@Props、@Link、@Provide、@Consume、@Observed、@ObjectLink)仅能在页面内,即一个组件树上共享状态变量。

如果开发者要实现应用级的,或者多个页面的状态数据共享,就需要用到应用级别的状态管理的概念。ArkTS根据不同特性,提供了多种应用状态管理的能力:

  • LocalStorage:页面级UI状态存储,通常用于UIAbility内、页面间的状态共享。

  • AppStorage:特殊的单例LocalStorage对象,由UI框架在应用程序启动时创建,为应用程序UI状态属性提供中央存储;

  • PersistentStorage:持久化存储UI状态,通常和AppStorage配合使用,选择AppStorage存储的数据写入磁盘,以确保这些属性在应用程序重新启动时的值与应用程序关闭时的值相同;

  • Environment:应用程序运行的设备的环境参数,环境参数会同步到AppStorage中,可以和AppStorage搭配使用。

下面我们分别来了解他们。

2、LocalStorage: 页面级UI状态存储

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

本小节重点介绍LocalStorage使用场景和相关的装饰器:@LocalStorageProp和@LocalStorageLink。

LocalStorage是ArkTS为构建页面级别状态变量提供存储的内存内“数据库”,它有以下特点:

    • 应用程序可以创建多个LocalStorage实例,LocalStorage实例可以在页面内共享,也可以通过GetShared接口,实现跨页面、UIAbility实例内共享。

    • 组件树的根节点(即被@Entry装饰的@Component),可以被分配一个LocalStorage实例,此组件的所有子组件实例将自动获得对该LocalStorage实例的访问权限;

    • 被@Component装饰的组件最多可以访问一个LocalStorage实例和AppStorage,未被@Entry装饰的组件不可被独立分配LocalStorage实例,只能接受父组件通过@Entry传递来的LocalStorage实例。一个LocalStorage实例在组件树上可以被分配给多个组件。

    • LocalStorage中的所有属性都是可变的。

    • 应用程序决定LocalStorage对象的生命周期。当应用释放最后一个指向LocalStorage的引用时,比如销毁最后一个自定义组件,LocalStorage将被JS Engine垃圾回收。

它还有一些限制条件,如下:

    • LocalStorage创建后,命名属性的类型不可更改。后续调用Set时必须使用相同类型的值。

    • LocalStorage是页面级存储,GetShared接口仅能获取当前Stage通过windowStage.loadContent传入的LocalStorage实例,否则返回undefined。例子可见将LocalStorage实例从UIAbility共享到一个或多个视图。

LocalStorage根据与@Component装饰的组件的同步类型不同,提供了两个装饰器:

    • @LocalStorageProp:@LocalStorageProp装饰的变量和与LocalStorage中给定属性建立单向同步关系。

    • @LocalStorageLink:@LocalStorageLink装饰的变量和在@Component中创建与LocalStorage中给定属性建立双向同步关系。

【tips:我们前面的文章学习了@Prop和@Link装饰器,在见到@LocalStorageProp和@LocalStorageLink装饰器后,会不会有一种熟悉感?】

在鸿蒙中,Prop单词表示单向同步,Link单词表示双向同步,在有@Prop和@Link的学习知识后,我们大致也能够猜测,@LocalStorageProp是单向的数据传递,@LocalStorageLink是双向的数据传递。

2.1、@LocalStorageProp装饰器

@LocalStorageProp(key)是和LocalStorage中key对应的属性建立单向数据同步,我们允许本地改变的发生,但是对于@LocalStorageProp,本地的修改永远不会同步回LocalStorage中,相反,如果LocalStorage给定key的属性发生改变,改变会被同步给@LocalStorageProp,并覆盖掉本地的修改。它有以下特点:

  • 其允许装饰的变量类型为:Object、class、string、number、boolean、enum类型,以及这些类型的数组。

  • 装饰器参数必须为字符串,必填。

  • 必须指定初始值。

~~~上demo~~~

在下面的示例中,CompA 组件和Child组件分别在本地创建了与storage的'PropA'对应属性的单向同步的数据,我们可以看到:

  • CompA中对this.storProp1的修改,只会在CompA中生效,并没有同步回storage;

  • Child组件中,Text绑定的storProp2 依旧显示47。

// 创建新实例并使用给定对象初始化let storage = new LocalStorage({ 'PropA': 47 });// 使LocalStorage可从@Component组件访问@Entry(storage)@Componentstruct CompA {  // @LocalStorageProp变量装饰器与LocalStorage中的'PropA'属性建立单向绑定  @LocalStorageProp('PropA') storProp1: number = 1;  build() {    Column({ space: 15 }) {      // 点击后从47开始加1,只改变当前组件显示的storProp1,不会同步到LocalStorage中      Button(`Parent from LocalStorage ${this.storProp1}`)        .onClick(() => this.storProp1 += 1)      Child()    }  }}@Componentstruct Child {  // @LocalStorageProp变量装饰器与LocalStorage中的'PropA'属性建立单向绑定  @LocalStorageProp('PropA') storProp2: number = 2;  build() {    Column({ space: 15 }) {      // 当CompA改变时,当前storProp2不会改变,显示47      Text(`Parent from LocalStorage ${this.storProp2}`)    }  }}

图片

2.2、@LocalStorageLink装饰器

与前文所述的@LocalStorageProps类似,@LocalStorageLink的用法我们不再赘述,它与@LocalStorageProps的区别是,数据双向同步,我们将上文的demo改一下,将@LocalStorageProps改为@LocalStorageLink,我们将看到,两边的组件会同步更新。

// 创建新实例并使用给定对象初始化let storage = new LocalStorage({ 'PropA': 47 });// 使LocalStorage可从@Component组件访问@Entry(storage)@Componentstruct CompA {  // @LocalStorageProp变量装饰器与LocalStorage中的'PropA'属性建立单向绑定  @LocalStorageLink('PropA') storProp1: number = 1;  build() {    Column({ space: 15 }) {      // 点击后从47开始加1,只改变当前组件显示的storProp1,不会同步到LocalStorage中      Button(`Parent from LocalStorage ${this.storProp1}`)        .onClick(() => this.storProp1 += 1)      Child()    }  }}@Componentstruct Child {  // @LocalStorageProp变量装饰器与LocalStorage中的'PropA'属性建立单向绑定  @LocalStorageLink('PropA') storProp2: number = 2;  build() {    Column({ space: 15 }) {      // 当CompA改变时,当前storProp2不会改变,显示47      Text(`Parent from LocalStorage ${this.storProp2}`)    }  }}

图片

3、AppStorage: 页面级UI状态存储

AppStorage是应用全局的UI状态存储,是和应用的进程绑定的,由UI框架在应用程序启动时创建,为应用程序UI状态属性提供中央存储。

和AppStorage不同的是,LocalStorage是页面级的,通常应用于页面内的数据共享。而AppStorage是应用级的全局状态共享,还相当于整个应用的“中枢”,持久化数据PersistentStorage和环境变量Environment都是通过和AppStorage中转,才可以和UI交互。

AppStorage使用场景和相关的装饰器:@StorageProp和@StorageLink。

对的,你没看错,也是@***Prop和@***Link,轻车熟路,我们只看Prop,Link就当成双向同步的版本类似用即可。

~~~上demo~~~

AppStorage是单例,它的所有API都是静态的,使用方法类似于LocalStorage对应的非静态方法。​​​​​​​

AppStorage.SetOrCreate('PropA', 47);@Entry(storage)@Componentstruct CompA {  @StorageProp('PropA') storLink: number = 1;  build() {    Column({ space: 20 }) {      Text(`From AppStorage ${this.storLink}`)        .onClick(() => this.storLink += 1)      Text(`From LocalStorage ${this.localStorLink}`)        .onClick(() => this.localStorLink += 1)    }  }}

4、结语

PersistentStorage与Environment后续章节继续讨论,请持续关注:

“鸿蒙UI开发快速入门 —— part10”

如果你也对鸿蒙开发感兴趣,加入“Harmony自习室”吧!

扫描下面的二维码关注公众号。

图片

  • 26
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值