PersistentStorage:持久化存儲UI狀態(tài)

2024-01-25 12:06 更新

前兩個小節(jié)介紹的LocalStorage和AppStorage都是運行時的內(nèi)存,但是在應用退出再次啟動后,依然能保存選定的結(jié)果,是應用開發(fā)中十分常見的現(xiàn)象,這就需要用到PersistentStorage。

PersistentStorage是應用程序中的可選單例對象。此對象的作用是持久化存儲選定的AppStorage屬性,以確保這些屬性在應用程序重新啟動時的值與應用程序關(guān)閉時的值相同。

概述

PersistentStorage將選定的AppStorage屬性保留在設(shè)備磁盤上。應用程序通過API,以決定哪些AppStorage屬性應借助PersistentStorage持久化。UI和業(yè)務(wù)邏輯不直接訪問PersistentStorage中的屬性,所有屬性訪問都是對AppStorage的訪問,AppStorage中的更改會自動同步到PersistentStorage。

PersistentStorage和AppStorage中的屬性建立雙向同步。應用開發(fā)通常通過AppStorage訪問PersistentStorage,另外還有一些接口可以用于管理持久化屬性,但是業(yè)務(wù)邏輯始終是通過AppStorage獲取和設(shè)置屬性的。

限制條件

PersistentStorage允許的類型和值有:

  • number, string, boolean, enum 等簡單類型。
  • 可以被JSON.stringify()和JSON.parse()重構(gòu)的對象。例如Date, Map, Set等內(nèi)置類型則不支持,以及對象的屬性方法不支持持久化。

PersistentStorage不允許的類型和值有:

  • 不支持嵌套對象(對象數(shù)組,對象的屬性是對象等)。因為目前框架無法檢測AppStorage中嵌套對象(包括數(shù)組)值的變化,所以無法寫回到PersistentStorage中。
  • 不支持undefined 和 null 。

持久化數(shù)據(jù)是一個相對緩慢的操作,應用程序應避免以下情況:

  • 持久化大型數(shù)據(jù)集。
  • 持久化經(jīng)常變化的變量。

PersistentStorage的持久化變量最好是小于2kb的數(shù)據(jù),不要大量的數(shù)據(jù)持久化,因為PersistentStorage寫入磁盤的操作是同步的,大量的數(shù)據(jù)本地化讀寫會同步在UI線程中執(zhí)行,影響UI渲染性能。如果開發(fā)者需要存儲大量的數(shù)據(jù),建議使用數(shù)據(jù)庫api。

PersistentStorage只能在UI頁面內(nèi)使用,否則將無法持久化數(shù)據(jù)。

支持的接口

PersistProp

static PersistProp<T>(key: string, defaultValue: T): void

將AppStorage中key對應的屬性持久化到文件中。該接口的調(diào)用通常在訪問AppStorage之前。

確定屬性的類型和值的順序如下:

  1. 如果PersistentStorage文件中存在key對應的屬性,在AppStorage中創(chuàng)建對應的propName,并用在PersistentStorage中找到的key的屬性初始化。
  2. 如果PersistentStorage文件中沒有查詢到key對應的屬性,則在AppStorage中查找key對應的屬性。如果找到key對應的屬性,則將該屬性持久化。
  3. 如果AppStorage也沒查找到key對應的屬性,則在AppStorage中創(chuàng)建key對應的屬性。用defaultValue初始化其值,并將該屬性持久化。

根據(jù)上述的初始化流程,如果AppStorage中有該屬性,則會使用其值,覆蓋掉PersistentStorage文件中的值。由于AppStorage是內(nèi)存內(nèi)數(shù)據(jù),該行為會導致數(shù)據(jù)喪失持久化能力。

參數(shù):

參數(shù)名

類型

必填

參數(shù)描述

key

string

屬性名。

defaultValue

T

在PersistentStorage和AppStorage未查詢到時,則使用默認值初始化初始化它。不允許為undefined和null。

示例:

  1. PersistentStorage.PersistProp('highScore', '0');

DeleteProp

static DeleteProp(key: string): void

將key對應的屬性從PersistentStorage刪除,后續(xù)AppStorage的操作,對PersistentStorage不會再有影響。

參數(shù):

參數(shù)名

類型

必填

參數(shù)描述

key

string

PersistentStorage中的屬性名。

示例:

  1. PersistentStorage.DeleteProp('highScore');

PersistProps

static PersistProps(properties: {key: string, defaultValue: any;}[]): void

行為和PersistProp類似,不同在于可以一次性持久化多個數(shù)據(jù),適合在應用啟動的時候初始化。

參數(shù):

參數(shù)名

類型

必填

參數(shù)描述

key

string

屬性名。

properties

{key: string, defaultValue: any}[]

持久化數(shù)組,啟動key為屬性名,defaultValue為默認值。規(guī)則同PersistProp。

示例:

  1. PersistentStorage.PersistProps([{ key: 'highScore', defaultValue: '0' }, { key: 'wightScore', defaultValue: '1' }]);

Keys

static Keys(): Array<string>

返回所有持久化屬性的key的數(shù)組。

返回值:

類型

描述

Array<string>

返回所有持久化屬性的key的數(shù)組。

示例:

  1. let keys: Array<string> = PersistentStorage.Keys();

使用場景

從AppStorage中訪問PersistentStorage初始化的屬性

  1. 初始化PersistentStorage:
    1. PersistentStorage.PersistProp('aProp', 47);
  2. 在AppStorage獲取對應屬性:
    1. AppStorage.Get('aProp'); // returns 47

    或在組件內(nèi)部定義:

    1. @StorageLink('aProp') aProp: number = 48;

完整代碼如下:

  1. PersistentStorage.PersistProp('aProp', 47);
  2. @Entry
  3. @Component
  4. struct Index {
  5. @State message: string = 'Hello World'
  6. @StorageLink('aProp') aProp: number = 48
  7. build() {
  8. Row() {
  9. Column() {
  10. Text(this.message)
  11. // 應用退出時會保存當前結(jié)果。重新啟動后,會顯示上一次的保存結(jié)果
  12. Text(`${this.aProp}`)
  13. .onClick(() => {
  14. this.aProp += 1;
  15. })
  16. }
  17. }
  18. }
  19. }
說明

當前持久化存儲在API9模擬器上暫不支持。

  • 新應用安裝后首次啟動運行:
    1. 調(diào)用PersistProp初始化PersistentStorage,首先查詢在PersistentStorage本地文件中是否存在“aProp”,查詢結(jié)果為不存在,因為應用是第一次安裝。
    2. 接著查詢屬性“aProp”在AppStorage中是否存在,依舊不存在。
    3. 在AppStorge中創(chuàng)建名為“aProp”的number類型屬性,屬性初始值是定義的默認值47。
    4. PersistentStorage將屬性“aProp”和值47寫入磁盤,AppStorage中“aProp”對應的值和其后續(xù)的更改將被持久化。
    5. 在Index組件中創(chuàng)建狀態(tài)變量@StorageLink('aProp') aProp,和AppStorage中“aProp”雙向綁定,在創(chuàng)建的過程中會在AppStorage中查找,成功找到“aProp”,所以使用其在AppStorage找到的值47。
圖1 PersistProp初始化流程

  • 觸發(fā)點擊事件后:
    1. 狀態(tài)變量@StorageLink('aProp') aProp改變,觸發(fā)Text組件重新刷新。
    2. @StorageLink裝飾的變量是和AppStorage中建立雙向同步的,所以@StorageLink('aProp') aProp的變化會被同步回AppStorage中。
    3. AppStorage中“aProp”屬性的改變會同步到所有綁定該“aProp”的單向或者雙向變量,在本示例中沒有其他的綁定“aProp”的變量。
    4. 因為“aProp”對應的屬性已經(jīng)被持久化,所以在AppStorage中“aProp”的改變會觸發(fā)PersistentStorage將新的改變寫入本地磁盤。
  • 后續(xù)啟動應用:
    1. 執(zhí)行PersistentStorage.PersistProp('aProp', 47),在首先查詢在PersistentStorage本地文件查詢“aProp”屬性,成功查詢到。
    2. 將在PersistentStorage查詢到的值寫入AppStorage中。
    3. 在Index組件里,@StorageLink綁定的“aProp”為PersistentStorage寫入AppStorage中的值,即為上一次退出引用存入的值。

在PersistentStorage之前訪問AppStorage中的屬性

該示例為反例。在調(diào)用PersistentStorage.PersistProp或者PersistProps之前使用接口訪問AppStorage中的屬性是錯誤的,因為這樣的調(diào)用順序會丟失上一次應用程序運行中的屬性值:

  1. let aProp = AppStorage.SetOrCreate('aProp', 47);
  2. PersistentStorage.PersistProp('aProp', 48);

應用在非首次運行時,先執(zhí)行AppStorage.SetOrCreate('aProp', 47):屬性“aProp”在AppStorage中創(chuàng)建,其類型為number,其值設(shè)置為指定的默認值47。'aProp'是持久化的屬性,所以會被寫回PersistentStorage磁盤中,PersistentStorage存儲的上次退出應用的值丟失。

PersistentStorage.PersistProp('aProp', 48):在PersistentStorage中查找到“aProp”,找到,值為47。

以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號