arkts-state-mgmt-application-level.md 10.9 KB
Newer Older
1
# 应用级变量的状态管理
T
tianyu 已提交
2

L
luoying_ace_admin 已提交
3
在前面的章节中,已经讲述了如何管理页面级变量的状态,本章将说明如何管理应用级变量的状态,具体接口说明请参考[应用级变量的状态管理接口](../reference/arkui-ts/ts-state-management.md)
T
tianyu 已提交
4

L
luoying_ace_admin 已提交
5
## [AppStorage](../reference/arkui-ts/ts-state-management.md#appstorage)
T
tianyu 已提交
6 7 8 9 10 11 12 13 14 15 16

AppStorage是应用程序中的单例对象,由UI框架在应用程序启动时创建,在应用程序退出时销毁,为应用程序范围内的可变状态属性提供中央存储。

AppStorage包含整个应用程序中需要访问的所有状态属性,只要应用程序保持运行,AppStorage就会保存所有属性及属性值,属性值可以通过唯一的键值进行访问。

组件可以通过装饰器将应用程序状态数据与AppStorage进行同步,应用业务逻辑的实现也可以通过接口访问AppStorage。

AppStorage的选择状态属性可以与不同的数据源或数据接收器同步,这些数据源和接收器可以是设备上的本地或远程,并具有不同的功能,如数据持久性。这样的数据源和接收器可以独立于UI在业务逻辑中实现。

默认情况下,AppStorage中的属性是可变的,AppStorage还可使用不可变(只读)属性。

B
bojiang 已提交
17 18
> **说明**:[Worker](../reference/apis/js-apis-worker.md)和主线程只能通过[postMessage](../reference/apis/js-apis-worker.md#postmessage)交互,不能使用AppStorage进行交互。

T
tianyu 已提交
19 20 21 22 23 24
### @StorageLink装饰器

组件通过使用@StorageLink(key)装饰的状态变量,与AppStorage建立双向数据绑定,key为AppStorage中的属性键值。当创建包含@StorageLink的状态变量的组件时,该状态变量的值将使用AppStorage中的值进行初始化。在UI组件中对@StorageLink的状态变量所做的更改将同步到AppStorage,并从AppStorage同步到任何其他绑定实例中,如PersistentStorage或其他绑定的UI组件。

### @StorageProp装饰器

L
luoying_ace_admin 已提交
25
组件通过使用@StorageProp(key)装饰的状态变量,与AppStorage建立单向数据绑定,key标识AppStorage中的属性键值。当创建包含@StorageProp的状态变量的组件时,该状态变量的值将使用AppStorage中的值进行初始化。AppStorage中属性值的更改会导致绑定该状态变量的UI组件进行状态更新。
T
tianyu 已提交
26

27
### 示例
T
tianyu 已提交
28

L
luoying_ace_admin 已提交
29
每次用户单击Count按钮时,this.varA变量值都会增加1,此变量与AppStorage中的varA同步。每次用户单击language按钮时,修改AppStorage中的languageCode,此修改会同步给this.languageCode变量。 
T
tianyu 已提交
30 31 32 33 34 35 36

```ts
// xxx.ets
@Entry
@Component
struct ComponentA {
  @StorageLink('varA') varA: number = 2
L
luoying_ace_admin 已提交
37
  @StorageProp('languageCode') languageCode: string = 'en'
T
tianyu 已提交
38 39 40
  private label: string = 'count'

  aboutToAppear() {
L
luoying_ace_admin 已提交
41
    this.label = (this.languageCode === 'zh') ? '数量' : 'Count'
T
tianyu 已提交
42 43 44
  }

  build() {
L
luoying_ace_admin 已提交
45
    Column() {
T
tianyu 已提交
46 47 48 49 50
      Row({ space: 20 }) {
        Button(`${this.label}: ${this.varA}`)
          .onClick(() => {
            AppStorage.Set<number>('varA', AppStorage.Get<number>('varA') + 1)
          })
L
luoying_ace_admin 已提交
51
        Button(`language: ${this.languageCode}`)
T
tianyu 已提交
52
          .onClick(() => {
L
luoying_ace_admin 已提交
53
            if (AppStorage.Get<string>('languageCode') === 'zh') {
T
tianyu 已提交
54 55 56 57
              AppStorage.Set<string>('languageCode', 'en')
            } else {
              AppStorage.Set<string>('languageCode', 'zh')
            }
L
luoying_ace_admin 已提交
58
            this.label = (this.languageCode === 'zh') ? '数量' : 'Count'
T
tianyu 已提交
59 60 61
          })
      }
      .margin({ bottom: 50 })
L
luoying_ace_admin 已提交
62 63 64

      Row() {
        Button(`更改@StorageLink修饰的变量:${this.varA}`).height(40).fontSize(14)
T
tianyu 已提交
65 66 67 68
          .onClick(() => {
            this.varA++
          })
      }.margin({ bottom: 50 })
L
luoying_ace_admin 已提交
69 70 71

      Row() {
        Button(`更改@StorageProp修饰的变量:${this.languageCode}`).height(40).fontSize(14)
T
tianyu 已提交
72
          .onClick(() => {
L
luoying_ace_admin 已提交
73 74 75 76 77
            if (this.languageCode === 'zh') {
              this.languageCode = 'en'
            } else {
              this.languageCode = 'zh'
            }
T
tianyu 已提交
78 79 80 81 82 83 84
          })
      }
    }
  }
}
```

Y
yamila 已提交
85
![appstorage](figures/appstorage.gif)
T
tianyu 已提交
86

L
luoying_ace_admin 已提交
87
## [LocalStorage](../reference/arkui-ts/ts-state-management.md#localstorage9)
T
tianyu 已提交
88

L
luoying_ace_admin 已提交
89 90 91
> **说明:** 
> 
> 该组件从API version 9开始支持。后续版本如有新增内容,则采用上角标单独标记该内容的起始版本。
T
tianyu 已提交
92 93 94 95 96

LocalStorage是应用程序中的存储单元,生命周期跟随其关联的Ability。LocalStorage为应用程序范围内的可变状态属性和非可变状态属性提供存储,可变状态属性和非可变状态属性是构建应用程序UI的一部分,如一个Ability的UI。

应用层:一个应用程序可以创建多个LocalStorage实例,应用程序的每一个Ability对应一个LocalStorage实例。

L
luoying_ace_admin 已提交
97
Ability:一个应用程序可以拥有多个Ability,一个Ability中的所有子组件最多可以分配一个LocalStorage实例。并且,Ability中的所有子组件都将继承对此LocalStorage实例存储对象的访问权。
T
tianyu 已提交
98 99 100

一个组件最多可以访问一个LocalStorage实例,一个LocalStorage对象可以分配给多个组件。

101
### @LocalStorageLink装饰器
T
tianyu 已提交
102 103 104

组件通过使用@LocalStorageLink(key)装饰的状态变量,key值为LocalStorage中的属性键值,与LocalStorage建立双向数据绑定。当创建包含@LocalStorageLink的状态变量的组件时,该状态变量的值将会使用LocalStorage中的值进行初始化。如果LocalStorage中未定义初始值,将使用@LocalStorageLink定义的初始值。在UI组件中对@LocalStorageLink的状态变量所做的更改将同步到LocalStorage中,并从LocalStorage同步到Ability下的组件中。

105
### @LocalStorageProp装饰器
T
tianyu 已提交
106 107 108 109 110

组件通过使用LocalStorageProp(key)装饰的状态变量,key值为LocalStorage中的属性键值,与LocalStorage建立单向数据绑定。当创建包含@LocalStorageProp的状态变量的组件时,该状态变量的值将使用LocalStorage中的值进行初始化。LocalStorage中的属性值的更改会导致当前Ability下的所有UI组件进行状态更新。

> **说明:** 创建LocalStorage实例时如未定义初始值,可以使用组件内@LocalStorageLink和@LocalStorageProp的初始值。如果定义时给定了初始值,那么不会再使用@LocalStorageLink和@LocalStorageProp的初始值。

L
luoying_ace_admin 已提交
111
### 示例1(在一个Ability中创建LocalStorage)
T
tianyu 已提交
112

L
luoying_ace_admin 已提交
113
LocalStorage通过loadContent接口加载,接口说明详见[loadContent](../reference/apis/js-apis-window.md#loadcontent9-1)
T
tianyu 已提交
114

L
luoying_ace_admin 已提交
115 116
```ts
// MainAbility.ts
T
tianyu 已提交
117
import Ability from '@ohos.application.Ability'
L
luoying_ace_admin 已提交
118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147

export default class MainAbility extends Ability {
    storage: LocalStorage

    onCreate() {
        this.storage = new LocalStorage()
        this.storage.setOrCreate('storageSimpleProp', 121)
        console.info('[Demo MainAbility onCreate]')
    }

    onDestroy() {
        console.info('[Demo MainAbility onDestroy]')
    }

    onWindowStageCreate(windowStage) {
        // storage作为参数传递给loadContent接口
        windowStage.loadContent('pages/index', this.storage)
    }

    onWindowStageDestroy() {
        console.info('[Demo] MainAbility onWindowStageDestroy')
    }

    onForeground() {
        console.info('[Demo] MainAbility onForeground')
    }

    onBackground() {
        console.info('[Demo] MainAbility onBackground')
    }
T
tianyu 已提交
148 149 150 151 152
}
```

@Component组件获取数据

L
luoying_ace_admin 已提交
153 154
```ts
// index.ets
T
tianyu 已提交
155
let storage = LocalStorage.GetShared()
L
luoying_ace_admin 已提交
156

T
tianyu 已提交
157 158 159
@Entry(storage)
@Component
struct LocalStorageComponent {
L
luoying_ace_admin 已提交
160 161
  @LocalStorageLink('storageSimpleProp') simpleVarName: number = 0

T
tianyu 已提交
162
  build() {
L
luoying_ace_admin 已提交
163 164 165 166 167
    Column() {
      Button(`LocalStorageLink: ${this.simpleVarName.toString()}`)
        .margin(20)
        .onClick(() => {
          this.simpleVarName += 1
T
tianyu 已提交
168 169 170
        })
      Text(JSON.stringify(this.simpleVarName))
        .fontSize(50)
L
luoying_ace_admin 已提交
171 172
      LocalStorageComponentProp()
    }.width('100%')
B
bojiang 已提交
173 174
  }
}
L
luoying_ace_admin 已提交
175

B
bojiang 已提交
176 177
@Component
struct LocalStorageComponentProp {
L
luoying_ace_admin 已提交
178 179
  @LocalStorageProp('storageSimpleProp') simpleVarName: number = 0

B
bojiang 已提交
180 181
  build() {
    Column() {
L
luoying_ace_admin 已提交
182 183
      Button(`LocalStorageProp: ${this.simpleVarName.toString()}`)
        .margin(20)
B
bojiang 已提交
184
        .onClick(() => {
L
luoying_ace_admin 已提交
185
          this.simpleVarName += 1
B
bojiang 已提交
186 187 188
        })
      Text(JSON.stringify(this.simpleVarName))
        .fontSize(50)
L
luoying_ace_admin 已提交
189
    }.width('100%')
T
tianyu 已提交
190 191 192 193
  }
}
```

Y
yamila 已提交
194 195
![appstorage1](figures/appstorage1.gif)

T
tianyu 已提交
196 197
### 示例2(在Entry页面定义LocalStorage)

L
luoying_ace_admin 已提交
198 199 200 201
```ts
// xxx.ets
let storage = new LocalStorage({ "PropA": 47 })

T
tianyu 已提交
202
@Entry(storage)
L
luoying_ace_admin 已提交
203 204 205 206 207 208 209 210 211 212 213 214
@Component
struct ComA {
  @LocalStorageLink("PropA") storageLink: number = 1

  build() {
    Column() {
      Text(`Parent from LocalStorage ${this.storageLink}`)
        .fontSize(18)
        .margin(20)
        .onClick(() => this.storageLink += 1)
      Child()
    }
T
tianyu 已提交
215 216 217 218
  }
}

@Component
L
luoying_ace_admin 已提交
219 220 221 222 223 224 225 226
struct Child {
  @LocalStorageLink("PropA") storageLink: number = 1

  build() {
    Text(`Child from LocalStorage ${this.storageLink}`)
      .fontSize(18)
      .margin(20)
      .onClick(() => this.storageLink += 1)
T
tianyu 已提交
227 228 229 230
  }
}
```

Y
yamila 已提交
231 232
![appstorage2](figures/appstorage2.gif)

L
luoying_ace_admin 已提交
233
## [PersistentStorage](../reference/arkui-ts/ts-state-management.md#persistentstorage)
T
tianyu 已提交
234

L
luoying_ace_admin 已提交
235
PersistentStorage提供了一些静态方法用来管理应用持久化数据,可以将特定标记的持久化数据链接到AppStorage中,并由AppStorage接口访问对应持久化数据,或者通过@StorageLink装饰器来访问对应key的变量。 
T
tianyu 已提交
236 237 238

> **说明:**
>
L
luoying_ace_admin 已提交
239 240
> - PersistentStorage的PersistProp接口使用时,需要保证输入对应的key在AppStorage中存在。
> - PersistentStorage的DeleteProp接口使用时,只能对本次应用启动时已经link过的数据生效。
T
tianyu 已提交
241 242 243

```ts
// xxx.ets
L
luoying_ace_admin 已提交
244
PersistentStorage.PersistProp('highScore', '0')
T
tianyu 已提交
245 246 247 248

@Entry
@Component
struct PersistentComponent {
L
luoying_ace_admin 已提交
249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266
  @StorageLink('highScore') highScore: string = '0'
  @State currentScore: number = 0

  build() {
    Column() {
      if (this.currentScore === Number(this.highScore)) {
        Text(`new highScore : ${this.highScore}`).fontSize(18)
      }
      Button(`goal!, currentScore : ${this.currentScore}`)
        .margin(20)
        .onClick(() => {
          this.currentScore++
          if (this.currentScore > Number(this.highScore)) {
            this.highScore = this.currentScore.toString()
          }
        })
    }.width('100%')
  }
T
tianyu 已提交
267 268 269
}
```

Y
yamila 已提交
270 271
![appstorage3](figures/appstorage3.gif)

L
luoying_ace_admin 已提交
272
## [Environment](../reference/arkui-ts/ts-state-management.md#environment)
T
tianyu 已提交
273

L
luoying_ace_admin 已提交
274
Environment是框架在应用程序启动时创建的单例对象,它为AppStorage提供了一系列应用程序需要的环境状态数据,这些数据描述了应用程序运行的设备环境,包括系统语言、深浅色模式等等。Environment及其属性是不可变的,所有数据类型均为简单类型。如下示例展示了从Environment获取系统是否开启无障碍屏幕朗读:
T
tianyu 已提交
275

L
luoying_ace_admin 已提交
276 277 278
```ts
Environment.EnvProp('accessibilityEnabled', 'default')
var enable = AppStorage.Get('accessibilityEnabled')
T
tianyu 已提交
279 280
```

L
luoying_ace_admin 已提交
281
accessibilityEnabled是Environment提供的系统默认变量识别符。首先需要将对应系统属性绑定到AppStorage上,再通过AppStorage中的方法或者装饰器访问对应的系统属性数据。