HarmonyOS 应用级状态管理(LocalStorage、AppStorage、PersistentStorage)

news2024/12/23 13:52:12

HarmonyOS 应用级状态管理

1. LocalStorage:页面级UI状态存储

1.1 概念

  • LocalStorage是页面级的UI状态存储,通过@Entry装饰器接收的参数可以在页面内共享同一个LocalStorage实例。LocalStorage也可以在UIAbility内,页面间共享状态。
    • 应用程序可以创建多个LocalStorage实例,LocalStorage实例可以在页面内共享,也可以通过GetShared接口,获取在UIAbility里创建的GetShared,实现跨页面、UIAbility内共享。
    • 组件树的根节点,即被@Entry装饰的@Component,可以被分配一个LocalStorage实例,此组件的所有子组件实例将自动获得对该LocalStorage实例的访问权限;
    • 被@Component装饰的组件最多可以访问一个LocalStorage实例和AppStorage,未被@Entry装饰的组件不可被独立分配LocalStorage实例,只能接受父组件通过@Entry传递来的LocalStorage实例。一个LocalStorage实例在组件树上可以被分配给多个组件。
    • LocalStorage中的所有属性都是可变的

1.2 应用逻辑使用LocalStorage

/**
 * 和 js 用法几乎一致
 * 初始化的时候需要传入一个对象使用
 * 修改的时候通过key 修改 value的值
 */
const storage = new LocalStorage({name: "李四"})

storage.set('name', '张三')

console.log(storage.get("name"))



@Entry
@Component
struct LearnStorage {
  @State message: string = 'Hello World'

  build() {
    Row() {
      Column() {
        Text(this.message)
          .fontSize(50)
          .fontWeight(FontWeight.Bold)
      }
      .width('100%')
    }
    .height('100%')
  }
}

1.3 从UI内部使用LocalStorage(双向同步)

  • 除了应用程序逻辑使用LocalStorage,还可以借助LocalStorage相关的两个装饰器@LocalStorageProp和@LocalStorageLink,在UI组件内部获取到LocalStorage实例中存储的状态变量。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

1.3.1 例子
  • 使用构造函数创建LocalStorage实例storage;
  • 使用@Entry装饰器将storage添加到LearnStorage顶层组件中;
  • @LocalStorageLink绑定LocalStorage对给定的属性,建立双向数据同步
@Component
struct Child {
  // 子组件可以直接使用
  @LocalStorageLink('name') storageName: string = '张三';
  build() {
    Column() {
      Text('子组件---'+this.storageName)
    }
  }
}




/**
 * 和 js 用法几乎一致
 * 初始化的时候需要传入一个对象使用
 * 修改的时候通过key 修改 value的值
 */
const storage = new LocalStorage({})



@Entry(storage)
@Component
struct LearnStorage {

  /**
   * @LocalStorageLink变量装饰器与LocalStorage中的'name'属性建立双向绑定
   * 当@LocalStorageLink(key)装饰的数值改变被观察到时,修改将被同步回LocalStorage对应属性键值key的属性中。
   LocalStorage中属性键值key对应的数据一旦改变,属性键值key绑定的所有的数据(包括双向@LocalStorageLink和单向@LocalStorageProp)都将同步修改;
   当@LocalStorageLink(key)装饰的数据本身是状态变量,它的改变不仅仅会同步回LocalStorage中,还会引起所属的自定义组件的重新渲染

      必须指定默认值,如果localstorage对应的key里面有值优先取localstorage里面的值,没有则使用默认值
   */
  @LocalStorageLink('name') storageName: string = '张三';

  build() {
    Row() {
      Column() {
        Text(this.storageName)
          .fontSize(50)
          .fontWeight(FontWeight.Bold)
        Button('看看Storage').onClick(() => {
          this.storageName = '王五'
          // 也会打印王五
          console.log(storage.get('name'))
        })
        Child()
      }
      .width('100%')
    }
    .height('100%')
  }
}

1.4 从UI内部使用LocalStorage(单向同步)

@Component
struct Child {
  // 子组件可以直接使用
  @LocalStorageProp('name') storageName: string = '张三';
  build() {
    Column() {
      Text('子组件---'+this.storageName)
    }
  }
}




/**
 * 和 js 用法几乎一致
 * 初始化的时候需要传入一个对象使用
 * 修改的时候通过key 修改 value的值
 */
const storage = new LocalStorage({})



@Entry(storage)
@Component
struct LearnStorage {

  /**

   必须指定默认值,如果localstorage对应的key里面有值优先取localstorage里面的值,没有则使用默认值
   */
  @LocalStorageProp('name') storageName: string = '张三';

  build() {
    Row() {
      Column() {
        Text(this.storageName)
          .fontSize(50)
          .fontWeight(FontWeight.Bold)
        Button('看看Storage').onClick(() => {
          this.storageName = '王五'
          // 单项同步不会修改storage里的数据
          console.log(storage.get('name'))
        })
        Child()
      }
      .width('100%')
    }
    .height('100%')
  }
}

1.5 将LocalStorage实例从UIAbility共享到一个或多个视图(全局共享)

  • 上面的实例中,LocalStorage的实例仅仅在一个@Entry装饰的组件和其所属的子组件(一个页面)中共享,如果希望其在多个视图中共享,可以在所属UIAbility中创建LocalStorage实例,并调用windowStage.loadContent。
1.5.1 EntryAbility
import UIAbility from '@ohos.app.ability.UIAbility';
import hilog from '@ohos.hilog';
import window from '@ohos.window';

// 创建storage
const localStorage: LocalStorage = new LocalStorage({globalName: "全局的名字"});

export default class EntryAbility extends UIAbility {

  // 挂载到实例里
  storage: LocalStorage = localStorage


  onCreate(want, launchParam) {
    hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate');
  }

  onDestroy() {
    hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onDestroy');
  }

  async onWindowStageCreate(windowStage: window.WindowStage) {
    windowStage.loadContent('pages/LearnStorage', this.storage);
  }

  onWindowStageDestroy() {
    // Main window is destroyed, release UI related resources
    hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageDestroy');
  }

  onForeground() {
    // Ability has brought to foreground
    hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onForeground');
  }

  onBackground() {
    // Ability has back to background
    hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onBackground');
  }
}
1.5.2 页面中使用
// 通过GetShared接口获取stage共享的LocalStorage实例
const storage = LocalStorage.GetShared()

console.log(JSON.stringify(storage))
// 注入
@Entry(storage)
@Component
struct LearnStorage {

  /**
      注意:要在模拟器中运行
    使用prop单项绑定 或者 link双向绑定
   */
  @LocalStorageLink('globalName') globalName: string = '李四';
  // globalName = 'aa'

  build() {
    Row() {
      Column() {
        Text(this.globalName)
          .fontSize(50)
          .fontWeight(FontWeight.Bold)
        Button('看看Storage').onClick(() => {
          this.globalName = '王五'
          // 单项同步不会修改storage里的数据
          console.log(storage.get('name'))
        })
      }
      .width('100%')
    }
    .height('100%')
  }
}

2.AppStorage:应用全局的UI状态存储

2.1 概念

  • AppStorage是应用全局的UI状态存储,是和应用的进程绑定的,由UI框架在应用程序启动时创建,为应用程序UI状态属性提供中央存储。
  • 和AppStorage不同的是,LocalStorage是页面级的,通常应用于页面内的数据共享。而AppStorage是应用级的全局状态共享,还相当于整个应用的“中枢”,持久化数据PersistentStorage和环境变量Environment都是通过和AppStorage中转,才可以和UI交互。
  • AppStorage是在应用启动的时候会被创建的单例。它的目的是为了提供应用状态数据的中心存储,这些状态数据在应用级别都是可访问的。AppStorage将在应用运行过程保留其属性。属性通过唯一的键字符串值访问。
  • AppStorage可以和UI组件同步,且可以在应用业务逻辑中被访问。
  • AppStorage中的属性可以被双向同步,数据可以是存在于本地或远程设备上,并具有不同的功能,比如数据持久化(详见PersistentStorage)。这些数据是通过业务逻辑中实现,与UI解耦,如果希望这些数据在UI中使用,需要用到@StorageProp和@StorageLink

2.2 从应用逻辑使用AppStorage

  • AppStorage是单例,它的所有API都是静态的
// 有则修改没有则创建
AppStorage.SetOrCreate('name', 'app的名字');


console.log(AppStorage.Get('name'))


@Entry()
@Component
struct LearnStorage {

  build() {
    Row() {
      Column() {
        Text('哈哈哈')
      }
      .width('100%')
    }
    .height('100%')
  }
}

2.3 从UI内部使用AppStorage

  • @StorageLink变量装饰器与AppStorage配合使用,正如@LocalStorageLink与LocalStorage配合使用一样。此装饰器使用AppStorage中的属性创建双向数据同步
// 有则修改没有则创建
AppStorage.SetOrCreate('name', 'app的名字');


console.log(AppStorage.Get('name'))


@Entry()
@Component
struct LearnStorage {
  /**
   * 对AppStorage 里面的数据进行双向绑定
   * 同样使用prop为单向数据流
   */
  @StorageLink('name') name: string = '李四'

  build() {
    Row() {
      Column() {
        Text(this.name)
        Button('查看数据')
          .onClick(() => {
            this.name = '王五'
            // 数据也会改变
            console.log(AppStorage.Get('name'))
          })
      }
      .width('100%')
    }
    .height('100%')
  }
}

3.PersistentStorage:持久化存储UI状态

3.1 概念

  • PersistentStorage将选定的AppStorage属性保留在设备磁盘上。应用程序通过API,以决定哪些AppStorage属性应借助PersistentStorage持久化。UI和业务逻辑不直接访问PersistentStorage中的属性,所有属性访问都是对AppStorage的访问,AppStorage中的更改会自动同步到PersistentStorage。
  • PersistentStorage和AppStorage中的属性建立双向同步。应用开发通常通过AppStorage访问PersistentStorage,另外还有一些接口可以用于管理持久化属性,但是业务逻辑始终是通过AppStorage获取和设置属性的。

3.2 注意

3.2.1 允许的类型和值
    1. 使用简单类型如 number, string, boolean, enum。
    1. 可以使用 JSON.stringify() 和 JSON.parse() 的对象,但不支持内置类型如 Date, Map, Set。
3.2.2 不允许的类型和值
    1. 避免嵌套对象,包括对象数组和对象属性是对象。
    1. 不支持 undefined 和 null。
3.2.3 最佳实践和限制
    1. 避免持久化大型和经常变化的数据。
    1. 持久化变量最好小于 2kb。
    1. 不要过度持久化数据,可能影响 UI 渲染性能。
    1. 对于大量数据存储需求,建议使用数据库 API。
    1. 仅在 UI 页面内使用 PersistentStorage,否则无法持久化数据

3.3 使用

// 存入的数据会一直存在
PersistentStorage.PersistProp('token', '后端获取的token');
// 可以使用AppStorage 进行获取
console.log(AppStorage.Get('token'))

// 这样定义的不会持久化,应用被杀死 数据会丢失
// AppStorage.SetOrCreate('token', '小token')

@Entry()
@Component
struct LearnStorage {
  /**
   * 双向绑定
   * 也可以是会用StorageLink进行获取
   */
  @StorageLink('token') token: string = ''


  build() {
    Row() {
      Column() {
        Text(this.token)
        Button('修改数据')
          .onClick(() => {
            this.token = '修改的token,并且持久化'
          })
      }
      .width('100%')
    }
    .height('100%')
  }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2216663.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Linux】Linux下的Makefile基本操作

1.Makefile与 make介绍 在Linux中, Makefile 是⼀个⽂件, 令会在当前⽬录下找 make 是⼀个指令,当使⽤ Makefile ⽂件从⽽执⾏内部的内容 2.创建第一个 Makefile并使用make ⾸先,在当前⽬录下创建⼀个makefile文件 接下来在同级…

动态规划一>珠宝的最高价值

1.题目: 2.解析: 代码: /**1.创建dp表2.初始化3.填表4.返回*/public int jewelleryValue(int[][] frame) {int m frame.length, n frame[0].length;int[][] dp new int[m1][n1];//虚拟节点的值直接为0满足条件,已经初始化好…

字典树 计数问题(含 2022 icpc杭州 K)

//最近学了字典树,补一下 1.概念和实现 首先,字典树是一棵树(废话),边表示字母,从根到叶子节点所有边的顺序组合表示字目排列顺序。 看一下图明白很多: 例如:abc这个字母排序&am…

MybatisWebApp

如何构建一个有关Mybatis的Web&#xff1f; 在这里给出我自己的一些配置。我的TomCat版本&#xff1a;10.1.28 &#xff0c;IDEA版本&#xff1a;2024.1.4 Pom.XML文件 <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org/200…

Linux platform子系统和设备树

1 Linux platform子系统 在Linux 2.6内核中&#xff0c;提出了总线、设备、驱动的架构&#xff0c;目的是让我们写出来的驱动通用性更强。 arm核内部总线结构&#xff1a; 1.1 核心思想 将设备的信息从驱动中分离出来&#xff0c;我们需要在操作系统中&#xff0c;添加设备…

【H2O2|全栈】JS入门知识(二)

目录 JS 前言 准备工作 运算符 算数运算符 比较运算符 自增、自减运算符 逻辑运算符 运算符的优先级 分支语句 if-else语句 switch语句 三元表达式 结束语 JS 前言 本系列博客主要分享JavaScript的基础语法知识&#xff0c;本期为第二期&#xff0c;包含一些简…

平时使用Xshell能连接虚拟机,现在突然连接不上

问题&#xff1a;平时使用Xshell能连接虚拟机&#xff0c;现在突然连接不上&#xff0c;使用ip addr 命令查看ip地址 ens33 接口状态为 DOWN&#xff0c;没有分配IP地址&#xff0c;这通常意味着该网络接口未激活或存在配置问题。&#xff08;因为平时能连接&#xff0c;就说明…

mysql 09 独立表空间结构

表空间中的页实在是太多了&#xff0c;为了更好的管理这些页面&#xff0c;设计 InnoDB 的大叔们提出了 区 &#xff08;英文名&#xff1a; extent &#xff09;的概念。对于16KB的页来说&#xff0c;连续的64个页就是一个 区 &#xff0c;也就是说一个区默认占用1MB空间大小。…

农作物苹果叶片病虫害识别数据集

农作物苹果叶片病虫害识别数据集 一、引言 农作物病虫害是影响农业生产的重要因素之一&#xff0c;其中苹果作为广泛种植的水果品种&#xff0c;其叶片病虫害问题尤为突出。为了有效应对苹果叶片病虫害&#xff0c;提高苹果产量和品质&#xff0c;农业科研机构和学者不断开展…

2024软考网络工程师笔记 - 第4章.局域网和城域网

文章目录 局域网基础1️⃣局域网和城域网体系架构 IEEE&#xff08;负责链路层&#xff09;2️⃣局域网拓扑结构 &#x1f551;CSMA/CD1️⃣CSMA/CD2️⃣CSMA/CD三种监听算法3️⃣冲突检测原理 &#x1f552;二进制指数退避算法1️⃣ 二进制指数退避算法 &#x1f553;最小帧长…

你的抠图最快速度是多久?

前言 在图像处理的过程中&#xff0c;抠图速度和质量往往是大家非常关注的问题。那么&#xff0c;你的抠图最快速度是多久呢&#xff1f;今天我要给大家分享一个我用过的极为方便的抠图工具 —— 千鹿 AI。 只需要简单地上传图片&#xff0c;几秒钟后&#xff0c;就能得到一张…

【超详细】TCP协议

TCP(Transmission Control Protocol 传输控制协议) 传输层协议有连接可靠传输面向字节流 为什么TCP是传输控制协议呢&#xff1f; 我们以前所看到的write接口&#xff0c;都是把用户级缓冲区的数据拷贝到发送缓冲区中&#xff0c;然后数据就由TCP自主决定了&#xff0c;所以…

29.第二阶段x86游戏实战2-遍历周围-花指令与二叉树数据结构(有如何阅读vm代码混淆代码)

免责声明&#xff1a;内容仅供学习参考&#xff0c;请合法利用知识&#xff0c;禁止进行违法犯罪活动&#xff01; 本次游戏没法给 内容参考于&#xff1a;微尘网络安全 本人写的内容纯属胡编乱造&#xff0c;全都是合成造假&#xff0c;仅仅只是为了娱乐&#xff0c;请不要…

到底是微服务,还是SOA?

引言&#xff1a;大概正式工作有5年了&#xff0c;换了三个大厂【也是真特么世道艰难&#xff0c;中国互联网人才饱和了】。基本上每个公司有的架构都不太相同&#xff0c;干过TOC和TOB的业务&#xff0c;但是大家用的架构都不太相同。有坚持ALL in one的SB&#xff0c;最后服务…

windows下安装、配置neo4j并服务化启动

第一步&#xff1a;下载Neo4j压缩包 官网下载地址&#xff1a;https://neo4j.com/download-center/ &#xff08;官网下载真的非常慢&#xff0c;而且会自己中断&#xff0c;建议从以下链接下载&#xff09; 百度网盘下载地址&#xff1a;链接&#xff1a;https://pan.baid…

李生——2024年特别推荐中国品牌艺术家

李生北京人&#xff0c;字玄鹤、云鹤&#xff0c;号墨湖斋&#xff0c;玄鹤楼&#xff0c;中国共产党党员。主要成就:中国著名书法家、国家高级书法师、中国当代正能量文艺工作者:时代标杆等荣誉称号&#xff0c;现为中国东方文化研究会科教文化艺术专业委员会副研究员。自幼喜…

基于Python的博客系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码、微信小程序源码 精品专栏&#xff1a;…

JavaSE——泛型

目录 一、泛型的引入 二、泛型的好处 三、泛型介绍 四、泛型的语法 (一)泛型的声明 (二)泛型的实例化 五、泛型使用的注意事项和细节 六、泛型练习题1 七、自定义泛型 (一)自定义泛型类 (二)自定义泛型接口 (三)自定义泛型方法 八、泛型练习题2 九、泛型的继承和…

【Linux-进程间通信】vscode使用通信引入匿名管道引入

一、新系统&#xff0c;新软件 1.新系统 哈喽宝子们&#xff0c;从今以后我们不再使用风靡一时的CentOS系统了&#xff0c;因为CentOS已经不在维护了&#xff0c;各大公司几乎也都从CentOS转入其他操作系统了&#xff1b;我们现在由原来的CentOS系统切换到最新的Ubuntu系统&a…

向日葵下载教程以及三款远程控制工具推荐!!!

向日葵远程控制下载教程&#xff01;&#xff01; 亲爱的朋友们&#xff0c;如果你对远程控制软件有所需求&#xff0c;那么向日葵绝对是一个不错的选择。现在我将带你走一遍向日葵的下载流程。 1. 打开你的浏览器&#xff0c;输入“向日葵官方网站”&#xff0c;进入官方网站…