HarmonyOS数据持久化:Preferences轻量级存储实战

本文将详细介绍HarmonyOS 5(API 12)中的用户首选项(Preferences)数据持久化方案,通过实际代码示例讲解如何实现轻量级键值对数据的存储、读取和管理。

1. Preferences核心概念与优势

Preferences是HarmonyOS提供的轻量级键值对数据存储方案,适合保存用户偏好设置、应用配置信息等小规模数据。其核心优势包括操作简单、异步持久化以及支持多种基本数据类型。

1.1 适用场景

  • 用户偏好设置:主题模式、语言选择、通知开关
  • 应用配置信息:首次启动标志、显示选项、排序偏好
  • 轻量级数据缓存:用户ID、会话令牌、临时状态

1.2 特性与限制

  • Key限制:字符串类型,长度≤80字节,非空
  • Value类型:支持string、number、boolean及它们的数组形式
  • 存储容量:建议不超过50MB轻量级数据
  • 线程安全:不支持多进程并发访问

2. 基础API与使用步骤

2.1 模块导入与实例创建

首先导入必要的模块并创建Preferences实例:

复制代码
import { preferences } from '@kit.ArkData';
import { BusinessError } from '@ohos.base';
import common from '@ohos.app.ability.common';

// 获取应用上下文
const context: common.Context = getContext(this) as common.Context;

// 创建Preferences实例
let dataPreferences: preferences.Preferences | null = null;

async function initPreferences() {
  try {
    const options: preferences.Options = {
      name: 'myAppPreferences' // 首选项文件名
    };
    
    dataPreferences = preferences.getPreferencesSync(context, options);
    console.info('Preferences实例创建成功');
  } catch (error) {
    console.error(`Preferences初始化失败: ${(error as BusinessError).message}`);
  }
}

2.2 数据写入操作

Preferences支持多种数据类型的存储:

复制代码
// 写入字符串数据
dataPreferences.putSync('username', '张三');
dataPreferences.putSync('theme', 'dark');

// 写入数值数据
dataPreferences.putSync('font_size', 16);
dataPreferences.putSync('login_count', 1);

// 写入布尔值数据
dataPreferences.putSync('is_first_launch', true);
dataPreferences.putSync('notification_enabled', false);

// 写入数组数据
dataPreferences.putSync('recent_searches', ['华为', '鸿蒙', 'HarmonyOS']);

// 立即持久化到磁盘(可选)
dataPreferences.flush((err: BusinessError) => {
  if (err) {
    console.error(`数据持久化失败: ${err.message}`);
  } else {
    console.info('数据已持久化到磁盘');
  }
});

2.3 数据读取操作

读取存储的数据值:

复制代码
// 读取字符串数据(提供默认值)
const username = dataPreferences.getSync('username', '');
const theme = dataPreferences.getSync('theme', 'light');

// 读取数值数据
const fontSize = dataPreferences.getSync('font_size', 14);
const loginCount = dataPreferences.getSync('login_count', 0);

// 读取布尔值数据
const isFirstLaunch = dataPreferences.getSync('is_first_launch', true);
const notificationsEnabled = dataPreferences.getSync('notification_enabled', true);

// 读取数组数据
const recentSearches = dataPreferences.getSync('recent_searches', []);

console.info(`用户名: ${username}`);
console.info(`主题模式: ${theme}`);
console.info(`字体大小: ${fontSize}`);

2.4 数据删除与清理

复制代码
// 删除单个键值对
dataPreferences.deleteSync('is_first_launch');

// 检查键是否存在
const hasKey = dataPreferences.hasSync('username');
console.info(`username键存在: ${hasKey}`);

// 清空所有数据
dataPreferences.clearSync();

// 立即持久化清除操作
dataPreferences.flush((err: BusinessError) => {
  if (!err) {
    console.info('所有数据已清除并持久化');
  }
});

3. 完整实战示例:用户设置管理

下面是一个完整的用户设置管理实现示例:

复制代码
import { preferences } from '@kit.ArkData';
import { BusinessError } from '@ohos.base';
import common from '@ohos.app.ability.common';

@Entry
@Component
struct SettingsManager {
  private context: common.Context = getContext(this) as common.Context;
  private settingsPrefs: preferences.Preferences | null = null;
  
  @State theme: string = 'light';
  @State fontSize: number = 14;
  @State notificationsEnabled: boolean = true;
  @State isInitialized: boolean = false;

  // 初始化Preferences
  async aboutToAppear() {
    await this.initPreferences();
    await this.loadSettings();
    this.isInitialized = true;
  }

  private async initPreferences() {
    try {
      const options: preferences.Options = {
        name: 'user_settings'
      };
      
      this.settingsPrefs = preferences.getPreferencesSync(this.context, options);
      console.info('用户设置Preferences初始化成功');
    } catch (error) {
      console.error(`初始化失败: ${(error as BusinessError).message}`);
    }
  }

  // 加载用户设置
  private async loadSettings() {
    if (!this.settingsPrefs) return;

    this.theme = this.settingsPrefs.getSync('theme', 'light') as string;
    this.fontSize = this.settingsPrefs.getSync('font_size', 14) as number;
    this.notificationsEnabled = this.settingsPrefs.getSync('notifications_enabled', true) as boolean;
  }

  // 保存单一设置
  private async saveSetting(key: string, value: preferences.ValueType) {
    if (!this.settingsPrefs) return;

    try {
      this.settingsPrefs.putSync(key, value);
      await this.flushPreferences();
      console.info(`设置 ${key} 已保存`);
    } catch (error) {
      console.error(`保存设置失败: ${(error as BusinessError).message}`);
    }
  }

  // 持久化到磁盘
  private async flushPreferences(): Promise<void> {
    return new Promise((resolve, reject) => {
      if (!this.settingsPrefs) {
        reject('Preferences实例未初始化');
        return;
      }

      this.settingsPrefs.flush((err: BusinessError) => {
        if (err) {
          reject(err.message);
        } else {
          resolve();
        }
      });
    });
  }

  // 主题切换
  private async toggleTheme() {
    const newTheme = this.theme === 'light' ? 'dark' : 'light';
    this.theme = newTheme;
    await this.saveSetting('theme', newTheme);
  }

  // 字体大小调整
  private async adjustFontSize(increase: boolean) {
    const newSize = increase ? this.fontSize + 2 : this.fontSize - 2;
    this.fontSize = Math.max(12, Math.min(24, newSize)); // 限制范围12-24
    await this.saveSetting('font_size', this.fontSize);
  }

  // 通知开关切换
  private async toggleNotifications() {
    this.notificationsEnabled = !this.notificationsEnabled;
    await this.saveSetting('notifications_enabled', this.notificationsEnabled);
  }

  build() {
    Column({ space: 20 }) {
      Text('应用设置')
        .fontSize(24)
        .fontWeight(FontWeight.Bold)
        .margin({ top: 20, bottom: 30 })

      // 主题设置
      Row() {
        Text('主题模式:')
          .fontSize(18)
          .layoutWeight(1)
        
        Text(this.theme === 'light' ? '浅色' : '深色')
          .fontSize(16)
          .fontColor(this.theme === 'light' ? '#000000' : '#FFFFFF')
        
        Button('切换')
          .onClick(() => this.toggleTheme())
          .margin({ left: 10 })
      }
      .width('90%')
      .padding(10)
      .backgroundColor(this.theme === 'light' ? '#F5F5F5' : '#333333')

      // 字体大小设置
      Row() {
        Text('字体大小:')
          .fontSize(18)
          .layoutWeight(1)
        
        Text(this.fontSize.toString())
          .fontSize(16)
        
        Button('减小')
          .onClick(() => this.adjustFontSize(false))
          .margin({ left: 10 })
        
        Button('增大')
          .onClick(() => this.adjustFontSize(true))
          .margin({ left: 5 })
      }
      .width('90%')
      .padding(10)
      .backgroundColor(this.theme === 'light' ? '#F5F5F5' : '#333333')

      // 通知设置
      Row() {
        Text('消息通知:')
          .fontSize(18)
          .layoutWeight(1)
        
        Text(this.notificationsEnabled ? '开启' : '关闭')
          .fontSize(16)
        
        Button('切换')
          .onClick(() => this.toggleNotifications())
          .margin({ left: 10 })
      }
      .width('90%')
      .padding(10)
      .backgroundColor(this.theme === 'light' ? '#F5F5F5' : '#333333')

      // 状态显示
      if (this.isInitialized) {
        Text('设置已保存到本地存储')
          .fontSize(14)
          .fontColor(Color.Gray)
          .margin({ top: 20 })
      }
    }
    .width('100%')
    .height('100%')
    .backgroundColor(this.theme === 'light' ? '#FFFFFF' : '#000000')
  }
}

4. 高级特性与最佳实践

4.1 数据变更订阅

Preferences支持数据变更通知,可用于实现设置同步:

复制代码
// 订阅数据变更
private setupPreferenceListeners() {
  if (!this.settingsPrefs) return;

  const observer = (key: string) => {
    console.info(`设置项 ${key} 已变更`);
    this.loadSettings(); // 重新加载设置
  };

  // 添加变更监听
  this.settingsPrefs.on('change', observer);

  // 在组件销毁时移除监听
  this.settingsPrefs.off('change', observer);
}

4.2 错误处理与健壮性设计

复制代码
class SafePreferences {
  private prefs: preferences.Preferences | null = null;

  // 安全写入数据
  async safePut(key: string, value: preferences.ValueType): Promise<boolean> {
    try {
      if (!this.prefs) {
        throw new Error('Preferences实例未初始化');
      }

      this.prefs.putSync(key, value);
      await this.safeFlush();
      return true;
    } catch (error) {
      console.error(`数据写入失败: ${error.message}`);
      return false;
    }
  }

  // 安全读取数据
  safeGet<T extends preferences.ValueType>(key: string, defaultValue: T): T {
    try {
      if (!this.prefs) {
        throw new Error('Preferences实例未初始化');
      }

      return this.prefs.getSync(key, defaultValue) as T;
    } catch (error) {
      console.error(`数据读取失败: ${error.message}`);
      return defaultValue;
    }
  }

  // 安全持久化
  private async safeFlush(): Promise<boolean> {
    return new Promise((resolve) => {
      if (!this.prefs) {
        resolve(false);
        return;
      }

      this.prefs.flush((err: BusinessError) => {
        if (err) {
          console.error(`持久化失败: ${err.message}`);
          resolve(false);
        } else {
          resolve(true);
        }
      });
    });
  }
}

4.3 数据迁移与兼容性

复制代码
// 处理数据迁移
async migrateOldSettings() {
  const oldPrefs = preferences.getPreferencesSync(this.context, { name: 'old_settings' });
  const newPrefs = preferences.getPreferencesSync(this.context, { name: 'new_settings' });

  // 迁移数据
  const keys = ['theme', 'font_size', 'notifications_enabled'];
  for (const key of keys) {
    if (oldPrefs.hasSync(key)) {
      const value = oldPrefs.getSync(key, '');
      newPrefs.putSync(key, value);
    }
  }

  await newPrefs.flush();
  console.info('数据迁移完成');
}

5. 性能优化建议

  1. 批量操作:尽量减少flush调用次数,多个操作后统一flush

  2. 内存管理:及时清理不再使用的Preferences实例

  3. 数据量控制:单个Preferences文件存储数据不宜超过50MB

  4. 类型安全:使用TypeScript类型约束确保数据一致性

    // 批量操作示例
    async function saveMultipleSettings(settings: Record<string, preferences.ValueType>) {
    for (const [key, value] of Object.entries(settings)) {
    dataPreferences.putSync(key, value);
    }

    // 批量操作后统一持久化
    await dataPreferences.flush((err: BusinessError) => {
    if (!err) {
    console.info('批量设置保存成功');
    }
    });
    }

6. 总结

Preferences是HarmonyOS中简单易用的轻量级数据持久化方案,非常适合存储用户设置和应用配置信息。通过本文的介绍,您应该掌握:

  1. 基本操作:Preferences实例的创建、数据读写和删除
  2. 实战应用:实现完整的用户设置管理界面
  3. 高级特性:数据变更订阅、错误处理和迁移策略
  4. 性能优化:批量操作和内存管理最佳实践

Preferences虽然简单,但在实际开发中非常实用,合理使用可以显著提升应用的用户体验和稳定性。

关键注意事项

  • 避免存储敏感信息,Preferences不支持加密存储
  • 不适合存储大量数据或复杂关系型数据
  • 多进程环境下需要额外的同步机制

对于需要存储大量结构化数据或敏感信息的场景,建议考虑使用关系型数据库(RelationalStore)或其他安全存储方案。

需要参加鸿蒙认证的请点击 鸿蒙认证链接

相关推荐
Devil枫6 小时前
鸿蒙深链落地实战:从安全解析到异常兜底的全链路设计
安全·华为·harmonyos
广州腾科助你拿下华为认证7 小时前
华为考试:HCIE数通考试难度分析
大数据·华为
与天仙漫步星海7 小时前
华为基本命令
华为
低调小一13 小时前
Android传统开发 vs Android Compose vs HarmonyOS ArkUI 对照表
android·华为·harmonyos
程序员江同学15 小时前
ovCompose + AI 开发跨三端的 Now in Kotlin App
android·kotlin·harmonyos
猛码Memmat17 小时前
华为HarmonyOS开发文档
华为·harmonyos
祥睿夫子17 小时前
ArkTS 未被深挖的核心点:静态多态限制、静态成员与单例实战
harmonyos
高心星19 小时前
HarmonyOS 5.0应用开发——V2装饰器@local的使用
harmonyos