鸿蒙应用数据本地存储全攻略:从Preferences到SQLite

引言

在鸿蒙应用开发中,数据持久化是保证用户体验的关键环节。无论是保存用户偏好设置、缓存网络数据,还是管理复杂的结构化数据,鸿蒙系统都提供了多种成熟的本地存储方案。本文将深入探讨鸿蒙ArkTS开发中常用的数据存储技术,帮助开发者根据实际场景选择最合适的解决方案。

1 轻量级数据存储:Preferences

Preferences是鸿蒙中最简单的轻量级键值对存储方式,类似于Android的SharedPreferences,适用于保存用户配置信息、开关状态等小规模数据。

1.1 核心特性与使用场景

Preferences以键值对形式存储数据,支持string、number、boolean等基本数据类型。它采用XML文件格式存储,线程安全,但数据量不宜过大(建议不超过1MB)。

典型使用场景包括:
  • 用户主题设置(浅色/深色模式)
  • 语言偏好配置
  • 登录状态记忆
  • 应用开关状态记录

1.2 实战代码示例

import preferences from '@ohos.data.preferences';

// 封装Preferences工具类
class PreferencesUtil {
  private static prefs: preferences.Preferences;
  
  // 初始化Preferences实例
  static async getPreferences(context: Context, name: string): Promise<preferences.Preferences> {
    if (!this.prefs) {
      this.prefs = await preferences.getPreferences(context, name);
    }
    return this.prefs;
  }
  
  // 存储数据
  static async putValue(context: Context, key: string, value: preferences.ValueType) {
    const prefs = await this.getPreferences(context, 'user_settings');
    await prefs.put(key, value);
    await prefs.flush(); // 确保数据写入磁盘
  }
  
  // 读取数据
  static async getValue(context: Context, key: string, defaultValue: preferences.ValueType) {
    const prefs = await this.getPreferences(context, 'user_settings');
    return await prefs.get(key, defaultValue);
  }
}

// 在页面中使用
@Entry
@Component
struct SettingsPage {
  @State isDarkMode: boolean = false;
  
  async aboutToAppear() {
    this.isDarkMode = await PreferencesUtil.getValue(getContext(this), 'dark_mode', false);
  }
  
  build() {
    Column() {
      Toggle({isOn: this.isDarkMode})
        .onChange(async (value) => {
          this.isDarkMode = value;
          await PreferencesUtil.putValue(getContext(this), 'dark_mode', value);
        })
    }
  }
}

2 文件存储方案

对于大数据量或非结构化数据,文件存储是更合适的选择,如图片、文档、缓存文件等。

2.1 文件操作API详解

鸿蒙提供了fileio模块进行文件操作,支持创建、读取、写入和删除文件等操作。

import fileio from '@ohos.fileio';

class FileUtil {
  // 写入文件
  static async writeFile(path: string, content: string): Promise<void> {
    const fd = await fileio.open(path, fileio.OpenMode.CREATE | fileio.OpenMode.WRONLY);
    await fileio.write(fd, content);
    await fileio.close(fd);
  }
  
  // 读取文件
  static async readFile(path: string): Promise<string> {
    const fd = await fileio.open(path, fileio.OpenMode.READ_ONLY);
    const stat = await fileio.stat(path);
    const buf = new ArrayBuffer(stat.size);
    await fileio.read(fd, buf);
    await fileio.close(fd);
    
    const decoder = new TextDecoder('utf-8');
    return decoder.decode(buf);
  }
}

// 使用示例:缓存新闻数据
async function cacheNews(articles: string) {
  const path = '/data/storage/el2/base/cache/news.txt';
  await FileUtil.writeFile(path, articles);
}

2.2 文件存储最佳实践

  • 路径管理:使用应用沙箱路径,避免权限问题
  • 大文件处理:采用流式操作,避免内存溢出
  • 错误处理:妥善处理IO异常,增强应用稳定性

3 关系型数据库:SQLite

对于复杂结构化数据,鸿蒙内置了基于SQLite的关系型数据库支持,通过RelationalStore API提供完整的SQL功能。

3.1 数据库设计与初始化

import relationalStore from '@ohos.data.relationalstore';
import { BusinessError } from '@kit.BasicServicesKit';

class DBManager {
  static rdbStore: relationalStore.RdbStore;
  static context: Context;
  
  // 初始化数据库
  static async initDB(context: Context): Promise<void> {
    this.context = context;
    
    const config: relationalStore.StoreConfig = {
      name: 'user.db',
      securityLevel: relationalStore.SecurityLevel.S1
    };
    
    try {
      this.rdbStore = await relationalStore.getRdbStore(context, config);
      // 创建用户表
      await this.rdbStore.executeSql(
        `CREATE TABLE IF NOT EXISTS user (
          id INTEGER PRIMARY KEY AUTOINCREMENT,
          name TEXT NOT NULL,
          email TEXT UNIQUE,
          age INTEGER DEFAULT 0,
          created_time TEXT DEFAULT (datetime('now'))
        )`
      );
    } catch (err) {
      console.error('数据库初始化失败:', (err as BusinessError).message);
    }
  }
}

3.2 CRUD操作完整实现

// 增删改查操作示例
class UserDAO {
  // 插入数据
  static async insertUser(user: User): Promise<number> {
    const valueBucket: relationalStore.ValuesBucket = {
      name: user.name,
      email: user.email,
      age: user.age
    };
    
    return await DBManager.rdbStore.insert('user', valueBucket);
  }
  
  // 查询数据
  static async queryUsers(conditions?: string): Promise<User[]> {
    const predicates = new relationalStore.RdbPredicates('user');
    if (conditions) {
      // 设置查询条件
      predicates.equalTo('age', 25);
    }
    
    const resultSet = await DBManager.rdbStore.query(predicates, 
      ['id', 'name', 'email', 'age', 'created_time']);
    
    const users: User[] = [];
    while (resultSet.goToNextRow()) {
      users.push({
        id: resultSet.getLong(resultSet.getColumnIndex('id')),
        name: resultSet.getString(resultSet.getColumnIndex('name')),
        email: resultSet.getString(resultSet.getColumnIndex('email')),
        age: resultSet.getLong(resultSet.getColumnIndex('age'))
      });
    }
    
    resultSet.close();
    return users;
  }
  
  // 更新数据
  static async updateUser(id: number, user: User): Promise<number> {
    const valueBucket: relationalStore.ValuesBucket = {
      name: user.name,
      email: user.email,
      age: user.age
    };
    
    const predicates = new relationalStore.RdbPredicates('user');
    predicates.equalTo('id', id);
    
    return await DBManager.rdbStore.update(valueBucket, predicates);
  }
  
  // 删除数据
  static async deleteUser(id: number): Promise<number> {
    const predicates = new relationalStore.RdbPredicates('user');
    predicates.equalTo('id', id);
    
    return await DBManager.rdbStore.delete(predicates);
  }
}

3.3 数据库高级特性

  • 事务处理:保证数据一致性
  • 索引优化:提升查询性能
  • 数据库升级:平滑迁移数据方案

选型建议:

  • 简单配置数据:Preferences
  • 大文件或非结构化数据:文件存储
  • 复杂查询和关系型数据:SQLite数据库

结语

鸿蒙系统提供了全面而强大的数据本地存储解决方案,从简单的键值对存储到复杂的关系型数据库,能够满足不同场景下的数据持久化需求。在实际开发中,开发者应根据数据规模、结构复杂度和性能要求选择合适的存储方案,同时注意数据安全性和用户体验,才能构建出高质量的应用。

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容