写点什么

鸿蒙 NEXT 开发 - 应用状态

作者:东林知识库
  • 2025-03-31
    江苏
  • 本文字数:5095 字

    阅读完需:约 17 分钟

1. 应用状态基本介绍

  • LocalStorage:页面级 UI 状态存储,通常用于UIAbility内、页面间的状态共享。(内存- 注意:和前端的区分开,它非持久化,非全应用)

  • AppStorage:特殊的单例 LocalStorage 对象,由 UI 框架在应用程序启动时创建,为应用程序 UI 状态属性提供中央存储。(内存-非持久化-退出应用同样消失)

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

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


官方文档地址:


文档中心

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

2.1 基本介绍

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

2.2 用法

用法


  • 创建 LocalStorage 实例:const storage = new LocalStorage({ key: value })

  • 单向 @LocalStorageProp('user') 组件内可变

  • 双向 @LocalStorageLink('user') 全局均可变

2.3 两个页面共享一个对象

  • 创建一个共享的状态


export class PersonModel {  username: string = '张三'  age: number = 18}
let pp = new PersonModel()pp.username = "东林"pp.age = 29// 创建新实例并使用给定对象初始化let para: Record<string, PersonModel> = { 'user': pp };let local: LocalStorage = new LocalStorage(para);
export { local }
复制代码


  • 页面 1


import { local, PersonModel } from '../models/PersonModel'import { router } from '@kit.ArkUI'
@Entry(local) @Component struct LocalStorageCaseA { @LocalStorageLink("user") user: PersonModel = new PersonModel
build() { Column() { Text(this.user.username) .fontSize(40) .onClick(() => { this.user.username = "王八蛋" router.pushUrl({url:'pages/LocalStorageCaseB'}) })
} .height('100%') .width('100%') } }
复制代码


  • 页面 2


import { local, PersonModel } from '../models/PersonModel'import { router } from '@kit.ArkUI'
@Entry(local) @Component struct LocalStorageCaseB { @LocalStorageLink("user") user: PersonModel = new PersonModel() build() { Column() { Text(this.user.username) .fontSize(50) .fontWeight(FontWeight.Bold) .onClick(() => { this.user.username = "李四" router.back() })
Text(this.user.age.toString()) .fontSize(50) .fontWeight(FontWeight.Bold) } .height('100%') .width('100%') } }
复制代码

2.4 页面间共享

如果你想在UIAbility中共享某个 localStorage,可以在入口处直接初始化传入


  • 可以在 loadContent 过程中直接传入创建的 LocalStorage

  • const storage = LocalStorage.GetShared() 得到实例

  • 通过 @Entry(storage) 传入页面

  • 在 UIAbility 进行初始化 storage


class UserInfoClass {  name?: string = ""  age?: number = 0}let user: Record<string, UserInfoClass> = { "user": {  name: '水若寒宇',  age: 34}};const sharedStorage = new LocalStorage(user)
onWindowStageCreate(windowStage: window.WindowStage): void { // Main window is created, set main page for this ability hilog.info(0x0000, 'testUIAbility', '%{public}s', 'Ability onWindowStageCreate');
windowStage.loadContent('pages/Index',local, (err) => { if (err.code) { hilog.error(0x0000, 'testUIAbility', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? ''); return; } hilog.info(0x0000, 'testUIAbility', 'Succeeded in loading the content.'); });}
复制代码


  • 在页面中传入


const shareLocal = LocalStorage.GetShared()@Entry(shareLocal)
复制代码

2.5 应用逻辑中使用

@Entry  @Component  struct Index {    build() {      Button('应用逻辑中使用')        .onClick(()=>{          let para: Record<string,number> = { 'PropA': 47 };          let storage: LocalStorage = new LocalStorage(para); // 创建新实例并使用给定对象初始化          let propA: number | undefined = storage.get('PropA') // propA == 47          console.log(propA?.toString())          let link1: SubscribedAbstractProperty<number> = storage.link('PropA'); // link1.get() == 47          let link2: SubscribedAbstractProperty<number> = storage.link('PropA'); // link2.get() == 47          let prop: SubscribedAbstractProperty<number> = storage.prop('PropA'); // prop.get() == 47          link1.set(48); // two-way sync: link1.get() == link2.get() == prop.get() == 48          prop.set(1); // one-way sync: prop.get() == 1; but link1.get() == link2.get() == 48          link1.set(49); // two-way sync: link1.get() == link2.get() == prop.get() == 49
})
} }
复制代码

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

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


一个应用可能有若干个 UIAbility

3.1 基本介绍

概述


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


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


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


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

3.2 基本用法

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


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


  • 如果是初始化使用 **AppStorage.setOrCreate(key,value)**

  • 单向 **@StorageProp('user')** 组件内可变

  • 双向 **@StorageLink('user')** 全局均可变


第二种用法 使用 API 方法


  • **AppStorage.get<ValueType>(key)** 获取数据

  • **AppStorage.set<ValueType>(key,value)** 覆盖数据

  • **const link: SubscribedAbstractProperty<ValueType> = AppStorage.Link(key)** 覆盖数据

  • **link.set(value)** 修改

  • **link.get()** 获取

3.3 经常使用的方法

// 存数据AppStorage.setOrCreate("token", "123456")AppStorage.setOrCreate<string>("username", "东林")// 获取数据const token: string | undefined = AppStorage.get("token")const username = AppStorage.get<string>("username")// 删除数据AppStorage.delete("token")
复制代码

3.4 代码示例

import { promptAction, router } from '@kit.ArkUI'
@Entry @Component struct AppStorageCase { @State username: string = "admin" @State password: string = "123456"
login() { if (this.username === 'admin' && this.password === "123456") { // 要将当前用户的身份存入AppStorage AppStorage.setOrCreate<UserInfoModel>("userInfo", new UserInfoModel('东林', 20)) router.pushUrl({ url: 'pages/Detail' }) } else { promptAction.showToast({ message: '登录失败' }) } }
build() { Row() { Column({ space: 20 }) { TextInput({ placeholder: '请输入用户名', text: $$this.username })
TextInput({ placeholder: '请输入密码', text: $$this.password }) .type(InputType.Password) Button("登录") .width('100%') .onClick(() => { this.login() }) } .padding(20) .width('100%') } .height('100%') } }

export class UserInfoModel { username: string = '' age: number = 0
constructor(username: string, age: number) { this.username = username this.age = age }}
复制代码


import { UserInfoModel } from './Index'
@Entry @Component struct Detail { @State userInfo: UserInfoModel | null | undefined = null
aboutToAppear(): void { const userInfo = AppStorage.get<UserInfoModel>("userInfo") this.userInfo = userInfo }
build() { Column() { Text(this.userInfo?.username) Text(this.userInfo?.age.toString()) } .height('100%') .width('100%') } }
复制代码

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

前两个小节介绍的 LocalStorage 和 AppStorage 都是运行时的内存,但是在应用退出再次启动后,依然能保存选定的结果,是应用开发中十分常见的现象,这就需要用到 PersistentStorage。


PersistentStorage 是应用程序中的可选单例对象。此对象的作用是持久化存储选定的 AppStorage 属性,以确保这些属性在应用程序重新启动时的值与应用程序关闭时的值相同。

4.1 基本介绍

概述


PersistentStorage 将选定的 AppStorage 属性保留在设备磁盘上。应用程序通过 API,以决定哪些 AppStorage 属性应借助 PersistentStorage 持久化。UI 和业务逻辑不直接访问 PersistentStorage 中的属性,所有属性访问都是对 AppStorage 的访问,AppStorage 中的更改会自动同步到 PersistentStorage。


PersistentStorage 和 AppStorage 中的属性建立双向同步。应用开发通常通过 AppStorage 访问 PersistentStorage,另外还有一些接口可以用于管理持久化属性,但是业务逻辑始终是通过 AppStorage 获取和设置属性的。

4.2 限制条件

PersistentStorage 允许的类型和值有:


  • number, string, boolean, enum 等简单类型。

  • 可以被 JSON.stringify()和 JSON.parse()重构的对象。例如 Date, Map, Set 等内置类型则不支持,以及对象的属性方法不支持持久化。


PersistentStorage 不允许的类型和值有:


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

  • 不支持 undefined 和 null 。

4.3 使用场景

从 AppStorage 中访问 PersistentStorage 初始化的属性


@Entry  @Component  struct Index {    build() {      Column() {        Button('点我')          .onClick(() => {            PersistentStorage.persistProp<string>('test', '123456');            const test = AppStorage.get<string>('test'); // returns 47            console.log(test)          })      }.width('100%')        .height('100%')    }  }
复制代码


官方参考文档:


文档中心

5. Environment:设备环境

5.1 概述

开发者如果需要应用程序运行的设备的环境参数,以此来作出不同的场景判断,比如多语言,深浅色模式等,需要用到 Environment 设备环境查询。


Environment 是 ArkUI 框架在应用程序启动时创建的单例对象。它为 AppStorage 提供了一系列描述应用程序运行状态的属性。Environment 的所有属性都是不可变的(即应用不可写入),所有的属性都是简单类型。

5.2 限制条件

Environment 的所有属性都是不可变的(即应用不可写入),所有的属性都是简单类型。

5.3 使用场景

想要知道当前系统的所使用的语言,然后把信息共享给应用内所有页面使用


注意:记得使用模拟器或者真机读取语言


import i18n from '@ohos.i18n'const lang=i18n.getSystemLanguage()console.log('lang test:'+lang);Environment.envProp('lang',lang)@Entry  @Component  struct Index {    @StorageProp('lang')    lang:string=''    build() {      Column(){        Text(lang)      }.width('100%')        .height('100%')
} }
复制代码


发布于: 2 小时前阅读数: 8
用户头像

享受当下,享受生活,享受成长乐趣! 2025-02-26 加入

鸿蒙、Java、大数据

评论

发布
暂无评论
鸿蒙NEXT开发-应用状态_东林知识库_InfoQ写作社区