HarmonyOS应用开发——应用状态

1. UIAbility内状态-LocalStorage

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

用法:

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

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

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

案例- 两个页面共享一个user对象

(1)页面1,代码如下:

import router from '@ohos.router'

export interface UserInfo {

name: string

age: number

}

export class UserInfoClass implements UserInfo {

name: string = ""

age: number = 0

}

let user: Record<string, UserInfoClass> = { "user": {

name: '王老五',

age: 34

}};

export let storage: LocalStorage = new LocalStorage(user);

@Entry(storage)

@Component

struct LocalStorageCase {

@State message: string = 'Hello World'

@LocalStorageProp("user")

myUser: UserInfoClass = {} as UserInfoClass

build() {

Row() {

Column({ space: 15 }) {

Text("姓名:" + this.myUser.name)

Text("年龄:" + this.myUser.age)

Button("跳转到另一个页面")

.onClick(() => {

router.pushUrl({

url: 'pages/LocalStorageCase2'

})

})

}

.width('100%')

}

.height('100%')

}

}

实现效果,如图所示:

点击"跳转到另一个页面"按钮到页面2.

(2)页面2,代码如下:

import {storage,UserInfoClass} from './LocalStorageCase'

@Entry(storage)

@Component

struct LocalStorageCase2 {

@LocalStorageProp("user")

myUser: UserInfoClass = new UserInfoClass() as UserInfoClass

build() {

Row() {

Column() {

Column({ space: 15 }) {

Text("姓名:" + this.myUser.name)

Text("年龄:" + this.myUser.age)

}

.width('100%')

}

.width('100%')

}

.height('100%')

}

}

实现效果,如图所示。

(3)使用LocalStorageLink实现双向绑定,代码如下:

import {storage,UserInfoClass} from './LocalStorageCase'

@Entry(storage)

@Component

struct LocalStorageCase2 {

@LocalStorageProp("user")

myUser: UserInfoClass = new UserInfoClass() as UserInfoClass

@LocalStorageLink("user")

myUser2: UserInfoClass = {} as UserInfoClass

build() {

Row() {

Column() {

Column({ space: 15 }) {

Text("姓名:" + this.myUser.name)

Text("年龄:" + this.myUser.age)

}

.width('100%')

Button("改名")

.onClick(() => {

this.myUser2.name = '赵老六'

})

}

.width('100%')

}

.height('100%')

}

}

实现效果,如图所示:

2. 应用状态-AppStorage

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

一个应用可能有若干个UIAbility。

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() 获取

需求-登录页A-存入token到全局状态,跳转到B页面,B页面检查token是否存在。

A页面,代码如下:

import router from '@ohos.router'

import promptAction from '@ohos.promptAction'

@Entry

@Component

struct AppStorageCase {

@StorageProp("user_token")

token: string = ''

@StorageLink("user_token")

linkToken: string = ''

onPageShow() {

promptAction.showToast({

message: AppStorage.Get<string>("user_token") || '无token'

})

}

build() {

Row() {

Column() {

Text(this.token)

Button("登录")

.onClick(() => {

AppStorage.SetOrCreate<string>("user_token", "123456")

router.pushUrl({

url: 'pages/AppStorageCase02'

})

})

Button("修改token")

.onClick(() => {

// this.linkToken = '678910'

const link = AppStorage.Link("user_token") as SubscribedAbstractProperty<string>

link.set("abcde")

})

}

.width('100%')

}

.height('100%')

}

}

实现效果,如图所示:

点击"登录",如图所示:

B页面,代码如下:

import router from '@ohos.router'

import promptAction from '@ohos.promptAction'

PersistentStorage.PersistProp("user_token", '') // 初始化磁盘

@Entry

@Component

struct AppStorageCase02 {

@StorageProp("user_token")

token: string = ''

@Watch('update')

@StorageLink("user_token")

linkToken: string = ''

onPageShow() {

promptAction.showToast({

message: AppStorage.Get<string>("user_token") || '无token'

})

}

update() {

promptAction.showToast({ message: 'token修改了' })

}

build() {

Row() {

Column() {

Text(this.linkToken)

Button("登录")

.onClick(() => {

AppStorage.SetOrCreate<string>("user_token", "123456")

router.pushUrl({

url: 'pages/AppStorageCaseTrans'

})

})

Button("修改token")

.onClick(() => {

// this.linkToken = '678910'

// const link = AppStorage.Link("user_token") as SubscribedAbstractProperty<string>

// link.set("abcde")

AppStorage.Set("user_token", 'cdcdscd')

// this.linkToken = 'dcscsdcdcd'

})

}

.width('100%')

}

.height('100%')

}

}

实现效果,如图所示:

点击"修改token"按钮,如图所示:

3. 状态持久化-PersistentStorage

前面讲的所有状态均为内存状态,也就是应用退出便消失,所以如果我们想持久化的保留一些数据,应该使用PersistentStorage。

注意:

UI和业务逻辑不直接访问 PersistentStorage 中的属性,所有属性访问都是对 AppStorage 的访问,AppStorage 中的更改会自动同步到 PersistentStorage。

也就是,我们和之前访问AppStorage是一样的,只不过需要提前使用PersistentStorage来声明。

PersistentStorage 将选定的 AppStorage 属性保留在设备磁盘上。

  • 支持:number, string, boolean, enum 等简单类型。
  • 如果:要支持对象类型,可以转换成json字符串。
  • 持久化变量最好是小于2kb的数据,如果开发者需要存储大量的数据,建议使用数据库api。

用法:

PersistentStorage.PersistProp('属性名', 值)

将刚刚的token直接持久化存储,代码如下。

(切记PersistentStorage放到app启动入口才会生效!!!)

PersistentStorage.PersistProp("user_token", '') // 初始化磁盘

完整代码如下:

import router from '@ohos.router'

import promptAction from '@ohos.promptAction'

PersistentStorage.persistProp("user_token", '11223344') // 初始化磁盘

@Entry

@Component

struct AppStorageCase02 {

@StorageProp("user_token")

token: string = ''

@Watch('update')

@StorageLink("user_token")

linkToken: string = ''

onPageShow() {

promptAction.showToast({

message: AppStorage.Get<string>("user_token") || '无token'

})

}

update() {

promptAction.showToast({ message: 'token修改了' })

}

build() {

Row() {

Column() {

Text(this.linkToken)

Button("登录")

.onClick(() => {

AppStorage.SetOrCreate<string>("user_token", "123456")

router.pushUrl({

url: 'pages/AppStorageCaseTrans'

})

})

Button("修改token")

.onClick(() => {

// this.linkToken = '678910'

// const link = AppStorage.Link("user_token") as SubscribedAbstractProperty<string>

// link.set("abcde")

AppStorage.set("user_token", '11223344')

// this.linkToken = 'dcscsdcdcd'

})

}

.width('100%')

}

.height('100%')

}

}

只要初始化了数据,我们以后使用AppStorage就可以读取和设置,它会自动同步到我们的磁盘上。

目前不支持复杂对象的持久化,如果需要存储,需要把它序列化成功字符串。

  • 测试:需要在真机或模拟器调试
  • 修改EntryAbility,代码如下:

windowStage.loadContent('pages/AppStorageCase', (err) => {

if (err.code) {

hilog.error(DOMAIN, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err));

return;

}

hilog.info(DOMAIN, 'testTag', 'Succeeded in loading the content.');

});

可以在上一个例子之前添加 PersistentStorage.PersistProp('属性名', 值)。

然后直接使用AppStorage进行Set就可以了,设置完成之后,使用模拟器先把任务销毁,然后再查看数据是否显示。

演示效果,如图所示:

欢迎加入课程班级,考取鸿蒙认证:

https://developer.huawei.com/consumer/cn/training/classDetail/d43582bb30b34f548c16c127cb3be104?type=1?ha_source=hmosclass\&ha_sourceId=89000248

相关推荐
前端不太难3 小时前
HarmonyOS 游戏里,Ability 是如何被重建的
游戏·状态模式·harmonyos
lbb 小魔仙4 小时前
【HarmonyOS实战】React Native 鸿蒙版实战:Calendar 日历组件完全指南
react native·react.js·harmonyos
一只大侠的侠4 小时前
Flutter开源鸿蒙跨平台训练营 Day 3
flutter·开源·harmonyos
盐焗西兰花4 小时前
鸿蒙学习实战之路-Reader Kit自定义字体最佳实践
学习·华为·harmonyos
_waylau4 小时前
鸿蒙架构师修炼之道-架构师的职责是什么?
开发语言·华为·harmonyos·鸿蒙
一只大侠的侠5 小时前
【Harmonyos】Flutter开源鸿蒙跨平台训练营 Day 2 鸿蒙跨平台开发环境搭建与工程实践
flutter·开源·harmonyos
小镇敲码人8 小时前
华为CANN框架中HCCL仓库的全面解析:分布式通信的引擎
分布式·华为
王码码20358 小时前
Flutter for OpenHarmony 实战之基础组件:第三十一篇 Chip 系列组件 — 灵活的标签化交互
android·flutter·交互·harmonyos
坚果派·白晓明9 小时前
在鸿蒙设备上快速验证由lycium工具快速交叉编译的C/C++三方库
c语言·c++·harmonyos·鸿蒙·编程语言·openharmony·三方库
小镇敲码人9 小时前
深入剖析华为CANN框架下的Ops-CV仓库:从入门到实战指南
c++·python·华为·cann