鴻蒙開發筆記-9-應用狀態管理:LocalStorage、AppStorage與PersistentStorage

一、基本概念

1. LocalStorage(頁面級內存存儲)

  • 專為單個UIAbility或頁面組件樹設計,支持通過@Entry裝飾器在根節點分配實例,子組件自動繼承訪問權限
  • 生命周期:與頁面綁定,最后一個引用釋放時由JS引擎回收,組件樹銷毀時自動回收
  • 實現原理:每個頁面獨立維護,銷毀時自動清除(API Version 11+支持跨頁面持久化)
  • 同步機制:
    • @LocalStorageProp:單向綁定(父→子),適用于展示型數據
    • @LocalStorageLink:雙向綁定(實時聯動),適合需要聯動的交互場景(如實時表單)

2. AppStorage(應用級全局狀態池)

  • 應用進程內全局狀態中樞,支持跨Ability/頁面共享,與PersistentStorage/Environment形成生態聯動
  • 生命周期:與進程綁定,應用啟動時創建,退出時銷毀(內存數據),但通過PersistentStorage可持久化
  • 實現原理:單例模式設計,通過裝飾器實現UI組件與狀態變量的雙向/單向綁定
  1. 初始化策略:
    • AppStorage.SetOrCreate('theme', 'dark') 實現懶加載式初始化
    • 支持復雜對象存儲(需配合@Observed裝飾器)
  2. 訪問方式:
    • @StorageProp:單向綁定(適合全局配置讀取)
    • @StorageLink:雙向綁定(如用戶登錄狀態全局同步)
  • 核心特性:
    • 支持復雜類型(Map/Set/Date等,需配合@Observed裝飾器)
    • 提供connect API實現類型安全的狀態訪問
    • 與PersistentStorage深度集成
    • 僅支持主線程訪問,非UI線程需通過Worker線程處理
    • 避免存儲超過2MB的大型對象
    • 高頻更新數據建議配合@Trace裝飾器使用

3. PersistentStorage(持久化存儲引擎)

  • 應用級持久化數據保險庫,實現"重啟不丟失"的數據持久
  • 實現原理:基于JSON序列化的磁盤存儲機制,通過觀察者模式監聽數據變更
  • 生命周期:數據永久存儲于設備磁盤,需通過AppStorage中轉操作
  • 關鍵技術
    • 類型白名單(支持number/string/boolean/enum/Map/Set/Date)
    • 異步持久化隊列(默認2KB/次寫入)
    • 增量更新機制(僅同步變更數據)
  • 典型場景:用戶偏好設置、離線緩存

二、對比分析

維度 LocalStorage AppStorage PersistentStorage
存儲位置 內存(頁面級) 內存(應用級) 磁盤(持久化)
數據類型 簡單類型+可序列化對象 復雜類型(需@Observed 簡單類型+部分復雜類型
同步方式 單向/雙向(內存操作) 雙向(內存操作) 異步持久化(磁盤IO)
安全風險 內存泄露風險 數據泄露/篡改風險
典型延遲 μs級 μs級 ms級(磁盤寫入)
適用場景 臨時狀態、頁面間通信 全局狀態共享 配置數據、歷史記錄

三、使用場景

1. LocalStorage
  • 頁面內多組件狀態共享
  • 動態樣式切換(主題/布局)
  • 表單數據臨時存儲
  • 示例:
typescript
// 頁面級主題管理
const storage = new LocalStorage({ 'theme': 'light' });

@Entry(storage)
@Component struct ThemePage {
  @LocalStorageLink('theme') currentTheme: string = 'light'
  
  build() {
    Column() {
      ThemeSwitcher({ theme: $$this.currentTheme })
      ContentArea()
    }.backgroundColor(this.currentTheme === 'dark' ? '#333' : '#FFF')
  }
}
2. AppStorage
  • 用戶全局偏好設置
  • 跨Ability數據共享
  • 應用級狀態管理(如登錄態)
  • 示例:
typescript
// 全局登錄狀態管理
AppStorage.setOrCreate('isLoggedIn', false)

@Entry
@Component struct MainEntry {
  @StorageLink('isLoggedIn') isLogin: boolean = false

  build() {
    Column() {
      if (this.isLogin) {
        HomePage()
      } else {
        LoginPage()
      }
    }
  }
}

關鍵特性

  • 類型推斷與編譯時校驗
  • 支持嵌套對象(需確保屬性可序列化)
3. PersistentStorage
  • 需要持久化的用戶設置
  • 離線緩存關鍵數據
  • 應用配置信息存儲
  • 示例:
typescript
// 持久化用戶設置
PersistentStorage.persistProp('userSettings', {
  fontSize: 14,
  notification: true
})

@Entry
@Component struct SettingsPage {
  @StorageLink('userSettings') settings: any = {}

  changeFontSize(size: number) {
    this.settings.fontSize = size
  }
}
4. PersistentStorage加密方案
// 靜態數據加密(AES-256)
import { cryptoFramework } from '@ohos.security.crypto';

async function securePersist(key: string, value: string) {
  const cipher = await cryptoFramework.createCipher('AES128|ECB|PKCS7', 'your-secret-key');
  const encrypted = cipher.encrypt(value);
  PersistentStorage.persistProp(key, encrypted);
}

安全建議

  • 敏感數據必須加密(推薦AES-256)
  • 結合哈希算法驗證數據完整性
5. PersistentStorage狀態更新策略
typescript
// 推薦更新方式
class UpdateService {
  static updateGlobalState(key: string, value: any) {
    if (needPersist(key)) {
      PersistentStorage.persistProp(key, value)
    }
    AppStorage.setOrCreate(key, value)
  }
}
6. 狀態恢復與容災
// 應用啟動時數據校驗
windowStage.loadContent('pages/Index', async (err) => {
  if (err) {
    console.error('Failed to load content:', err);
    return;
  }
  const lastData = await PersistentStorage.get('criticalData');
  if (!lastData) {
    // 從云端備份恢復
    const backup = await fetchBackup();
    PersistentStorage.persistProp('criticalData', backup);
  }
});

容災策略

  • 關鍵數據雙重存儲(本地+云端)
  • 定期測試備份恢復流程

四、總結

  • 優先使用LocalStorage處理頁面級狀態
  • 需要跨頁面共享時升級到AppStorage
  • 對關鍵配置數據使用PersistentStorage持久化
  • 對于高頻更新數據,建議使用AppStorage+內存緩存組合;對于敏感數據,必須啟用加密與完整性校驗。

我是今陽,如果想要進階和了解更多的干貨,歡迎關注微信公眾號 “今陽說” 接收我的最新文章

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容