📖 鸿蒙NEXT开发实战系列 | 第21篇 | 数据篇 🎯 适合人群:有鸿蒙基础的开发者 ⏰ 阅读时间:约15分钟 | 💻 开发环境:DevEco Studio 5.0+


⬅️ 上一篇20-网络篇-网络请求与数据加载
➡️ 下一篇22-数据篇-文件管理与沙箱机制


📑 目录


前言

你是否遇到过这样的问题:用户设置了一个深色主题,退出App后再打开,又变回了浅色主题?或者用户填写了一半的表单,App切到后台被系统回收,回来后数据全没了?

这些问题的根源都是:数据没有持久化

在鸿蒙开发中,数据持久化有三大利器,我称之为"三板斧":

  1. Preferences - 轻量级键值存储,适合简单配置

  2. RDB - 关系型数据库,适合结构化数据

  3. 分布式数据管理 - 跨设备数据同步

今天我们就来系统学习这三种方案,让你的App数据不再"失忆"!


一、数据持久化概述

1.1 为什么需要持久化

在鸿蒙应用中,变量存储在内存中,进程结束后内存被释放,数据自然就没了。持久化就是把数据从内存"搬到"磁盘上,这样即使App关闭、设备重启,数据依然存在。

1.2 鸿蒙存储体系

鸿蒙提供了多层次的存储方案:

存储方式

特点

适用场景

内存变量

速度快,进程结束即丢失

临时数据

Preferences

轻量KV,适合小数据

配置、开关

RDB

关系型,支持SQL

结构化业务数据

分布式KV

跨设备同步

多设备协同

文件存储

任意格式

大文件、媒体


二、Preferences:轻量级键值存储

2.1 什么是Preferences

Preferences(首选项)是一个轻量级的键值对存储方案,类似于Android的SharedPreferences或iOS的UserDefaults。它的特点是:

  • 简单易用:API简洁,几行代码搞定

  • 内存缓存:首次加载后缓存在内存,读取飞快

  • 适合小数据:建议存储数据量不超过几KB

典型应用场景

  • 用户设置(主题、语言、字号)

  • 开关状态(是否首次启动、通知开关)

  • 登录Token、用户信息缓存

2.2 基本使用

import { preferences } from '@kit.ArkData';

// 获取Preferences实例
const store = await preferences.getPreferences(context, 'myStore');

// 写入数据
await store.put('key', 'value');
await store.flush(); // 持久化到磁盘

// 读取数据
const value = await store.get('key', 'defaultValue');

// 删除数据
await store.delete('key');
await store.flush();

2.3 完整代码示例

下面是一个用户设置页面的完整示例,演示如何用Preferences保存用户偏好:

import { preferences } from '@kit.ArkData';
import { UIAbility, AbilityConstant, Want } from '@kit.AbilityKit';
import { hilog } from '@kit.PerformanceAnalysisKit';

// 定义设置项接口
interface UserSettings {
  theme: 'light' | 'dark';
  fontSize: number;
  notificationEnabled: boolean;
  language: string;
}

@Entry
@Component
struct SettingsPage {
  @State settings: UserSettings = {
    theme: 'light',
    fontSize: 16,
    notificationEnabled: true,
    language: 'zh-CN'
  };
  @State isLoading: boolean = true;

  // 获取Preferences实例
  private store: preferences.Preferences | null = null;

  async aboutToAppear() {
    await this.loadSettings();
  }

  // 加载设置
  async loadSettings() {
    try {
      const context = getContext(this);
      this.store = await preferences.getPreferences(context, 'userSettings');

      // 读取各项设置,带默认值
      this.settings = {
        theme: (await this.store.get('theme', 'light')) as 'light' | 'dark',
        fontSize: (await this.store.get('fontSize', 16)) as number,
        notificationEnabled: (await this.store.get('notificationEnabled', true)) as boolean,
        language: (await this.store.get('language', 'zh-CN')) as string
      };

      this.isLoading = false;
    } catch (err) {
      hilog.error(0x0000, 'SettingsPage', `加载设置失败: ${err}`);
    }
  }

  // 保存设置
  async saveSettings() {
    if (!this.store) return;

    try {
      await this.store.put('theme', this.settings.theme);
      await this.store.put('fontSize', this.settings.fontSize);
      await this.store.put('notificationEnabled', this.settings.notificationEnabled);
      await this.store.put('language', this.settings.language);

      // 关键:调用flush将内存数据写入磁盘
      await this.store.flush();
      hilog.info(0x0000, 'SettingsPage', '设置保存成功');
    } catch (err) {
      hilog.error(0x0000, 'SettingsPage', `保存设置失败: ${err}`);
    }
  }

  build() {
    Column() {
      if (this.isLoading) {
        LoadingProgress().width(50).height(50)
      } else {
        // 主题切换
        Row() {
          Text('深色模式').fontSize(16)
          Toggle({ type: ToggleType.Switch, isOn: this.settings.theme === 'dark' })
            .onChange(async (isOn) => {
              this.settings.theme = isOn ? 'dark' : 'light';
              await this.saveSettings();
            })
        }
        .width('100%')
        .padding(16)
        .justifyContent(FlexAlign.SpaceBetween)

        // 字号调节
        Row() {
          Text('字体大小').fontSize(16)
          Slider({
            value: this.settings.fontSize,
            min: 12,
            max: 24,
            step: 2
          })
            .onChange(async (value) => {
              this.settings.fontSize = value;
              await this.saveSettings();
            })
            .width(200)
        }
        .width('100%')
        .padding(16)
        .justifyContent(FlexAlign.SpaceBetween)

        // 通知开关
        Row() {
          Text('推送通知').fontSize(16)
          Toggle({ type: ToggleType.Switch, isOn: this.settings.notificationEnabled })
            .onChange(async (isOn) => {
              this.settings.notificationEnabled = isOn;
              await this.saveSettings();
            })
        }
        .width('100%')
        .padding(16)
        .justifyContent(FlexAlign.SpaceBetween)
      }
    }
    .width('100%')
    .height('100%')
    .backgroundColor('#F5F5F5')
  }
}

关键点说明

  1. 使用 preferences.getPreferences() 获取实例,同一个name共享同一个实例

  2. 写入后必须调用 flush() 才能持久化到磁盘

  3. 读取时可以设置默认值,防止key不存在时报错


三、RDB:关系型数据库

3.1 什么是RDB

RDB(Relational Database)是鸿蒙提供的关系型数据库,底层基于SQLite。相比Preferences,它适合存储更复杂、更大量的结构化数据。

典型应用场景

  • 聊天记录、消息列表

  • 用户数据、订单信息

  • 任何需要查询、排序、筛选的数据

3.2 基本使用

import { relationalStore } from '@kit.ArkData';

// 创建/获取数据库
const store = await relationalStore.getRdbStore(context, {
  name: 'myDB.db',
  securityLevel: relationalStore.SecurityLevel.S1
});

// 创建表
await store.executeSql('CREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY, name TEXT, age INTEGER)');

// 插入数据
const valueBucket: relationalStore.ValueBucket = { name: '张三', age: 25 };
const rowId = await store.insert('users', valueBucket);

// 查询数据
const predicates = new relationalStore.RdbPredicates('users');
predicates.equalTo('name', '张三');
const resultSet = await store.query(predicates, ['id', 'name', 'age']);

// 更新数据
const updateBucket: relationalStore.ValueBucket = { age: 26 };
predicates.equalTo('id', rowId);
await store.update(updateBucket, predicates);

// 删除数据
await store.delete(predicates);

3.3 完整代码示例

下面是一个待办事项App的完整示例:

import { relationalStore } from '@kit.ArkData';
import { hilog } from '@kit.PerformanceAnalysisKit';

// 定义Todo数据模型
interface TodoItem {
  id?: number;
  title: string;
  completed: boolean;
  createTime: number;
}

@Entry
@Component
struct TodoApp {
  @State todoList: TodoItem[] = [];
  @State newTodoTitle: string = '';
  private store: relationalStore.RdbStore | null = null;

  async aboutToAppear() {
    await this.initDatabase();
    await this.loadTodos();
  }

  // 初始化数据库
  async initDatabase() {
    try {
      const context = getContext(this);
      const config: relationalStore.StoreConfig = {
        name: 'todo.db',
        securityLevel: relationalStore.SecurityLevel.S1
      };

      this.store = await relationalStore.getRdbStore(context, config);

      // 创建表
      const createTableSql = `
        CREATE TABLE IF NOT EXISTS todos (
          id INTEGER PRIMARY KEY AUTOINCREMENT,
          title TEXT NOT NULL,
          completed INTEGER DEFAULT 0,
          createTime INTEGER
        )
      `;
      await this.store.executeSql(createTableSql);
      hilog.info(0x0000, 'TodoApp', '数据库初始化成功');
    } catch (err) {
      hilog.error(0x0000, 'TodoApp', `数据库初始化失败: ${err}`);
    }
  }

  // 加载待办列表
  async loadTodos() {
    if (!this.store) return;

    try {
      const predicates = new relationalStore.RdbPredicates('todos');
      predicates.orderByDesc('createTime');

      const resultSet = await this.store.query(predicates, ['id', 'title', 'completed', 'createTime']);

      const todos: TodoItem[] = [];
      while (resultSet.goToNextRow()) {
        todos.push({
          id: resultSet.getLong(resultSet.getColumnIndex('id')),
          title: resultSet.getString(resultSet.getColumnIndex('title')),
          completed: resultSet.getLong(resultSet.getColumnIndex('completed')) === 1,
          createTime: resultSet.getLong(resultSet.getColumnIndex('createTime'))
        });
      }
      resultSet.close();

      this.todoList = todos;
    } catch (err) {
      hilog.error(0x0000, 'TodoApp', `加载待办失败: ${err}`);
    }
  }

  // 添加待办
  async addTodo() {
    if (!this.store || !this.newTodoTitle.trim()) return;

    try {
      const valueBucket: relationalStore.ValueBucket = {
        title: this.newTodoTitle.trim(),
        completed: 0,
        createTime: Date.now()
      };

      await this.store.insert('todos', valueBucket);
      this.newTodoTitle = '';
      await this.loadTodos();
    } catch (err) {
      hilog.error(0x0000, 'TodoApp', `添加待办失败: ${err}`);
    }
  }

  // 切换完成状态
  async toggleTodo(item: TodoItem) {
    if (!this.store || !item.id) return;

    try {
      const predicates = new relationalStore.RdbPredicates('todos');
      predicates.equalTo('id', item.id);

      const valueBucket: relationalStore.ValueBucket = {
        completed: item.completed ? 0 : 1
      };

      await this.store.update(valueBucket, predicates);
      await this.loadTodos();
    } catch (err) {
      hilog.error(0x0000, 'TodoApp', `更新待办失败: ${err}`);
    }
  }

  // 删除待办
  async deleteTodo(id: number) {
    if (!this.store) return;

    try {
      const predicates = new relationalStore.RdbPredicates('todos');
      predicates.equalTo('id', id);

      await this.store.delete(predicates);
      await this.loadTodos();
    } catch (err) {
      hilog.error(0x0000, 'TodoApp', `删除待办失败: ${err}`);
    }
  }

  build() {
    Column() {
      // 标题
      Text('待办事项')
        .fontSize(24)
        .fontWeight(FontWeight.Bold)
        .padding(16)

      // 输入区域
      Row() {
        TextInput({ placeholder: '添加新的待办事项', text: this.newTodoTitle })
          .onChange((value) => this.newTodoTitle = value)
          .layoutWeight(1)
          .margin({ right: 8 })

        Button('添加')
          .onClick(() => this.addTodo())
          .width(80)
      }
      .padding(16)

      // 待办列表
      List({ space: 8 }) {
        ForEach(this.todoList, (item: TodoItem) => {
          ListItem() {
            Row() {
              Checkbox()
                .select(item.completed)
                .onChange(() => this.toggleTodo(item))
                .margin({ right: 12 })

              Text(item.title)
                .fontSize(16)
                .decoration({ type: item.completed ? TextDecorationType.LineThrough : TextDecorationType.None })
                .fontColor(item.completed ? '#999999' : '#333333')
                .layoutWeight(1)

              Button('删除')
                .type(ButtonType.Circle)
                .width(32)
                .height(32)
                .fontSize(12)
                .onClick(() => this.deleteTodo(item.id!))
            }
            .padding(12)
            .backgroundColor('#FFFFFF')
            .borderRadius(8)
          }
        })
      }
      .padding(16)
      .layoutWeight(1)
    }
    .width('100%')
    .height('100%')
    .backgroundColor('#F0F0F0')
  }
}

关键点说明

  1. 创建表时使用 executeSql() 执行SQL语句

  2. 使用 RdbPredicates 构建查询条件

  3. 查询结果需要手动遍历 ResultSet 获取数据

  4. 记得关闭 ResultSet 避免资源泄漏


四、分布式数据管理

4.1 什么是分布式KV

分布式数据管理是鸿蒙的特色能力,可以实现数据在多个设备间自动同步。想象一下:你在手机上设置了一个闹钟,平板上也能自动看到这个闹钟,这就是分布式数据的魔力。

分布式KV(Key-Value)是其中最常用的API,适合在多设备间同步简单的键值数据。

典型应用场景

  • 跨设备同步用户设置

  • 多设备协同办公数据

  • 分布式游戏存档

4.2 基本使用

import { distributedKVStore } from '@kit.ArkData';

// 创建KV管理器
const kvManager = distributedKVStore.createKVManager({
  bundleName: 'com.example.myapp',
  userInfo: { userId: '0', userType: distributedKVStore.UserType.SAME_USER_ID }
});

// 获取KVStore
const options: distributedKVStore.Options = {
  createIfMissing: true,
  encrypt: false,
  backup: false,
  autoSync: true
};
const kvStore = await kvManager.getKVStore('myStoreId', options);

// 写入数据
const entry: distributedKVStore.Entry = { key: 'theme', value: 'dark' };
await kvStore.put(entry.key, entry.value);

// 读取数据
const value = await kvStore.get('theme');

// 订阅数据变化
kvStore.on('dataChange', distributedKVStore.SubscribeType.SUBSCRIBE_TYPE_ALL, (data) => {
  console.log('数据变化:', data);
});

4.3 完整代码示例

下面是一个跨设备同步收藏列表的示例:

import { distributedKVStore } from '@kit.ArkData';
import { hilog } from '@kit.PerformanceAnalysisKit';
import { BusinessError } from '@kit.BasicServicesKit';

interface FavoriteItem {
  id: string;
  title: string;
  url: string;
  addTime: number;
}

@Entry
@Component
struct DistributedFavorites {
  @State favorites: FavoriteItem[] = [];
  @State syncStatus: string = '未连接';
  private kvStore: distributedKVStore.SingleKVStore | null = null;
  private kvManager: distributedKVStore.KVManager | null = null;

  async aboutToAppear() {
    await this.initDistributedStore();
  }

  // 初始化分布式存储
  async initDistributedStore() {
    try {
      // 创建KV管理器
      const managerConfig: distributedKVStore.ManagerConfig = {
        bundleName: 'com.example.myapp',
        userInfo: {
          userId: '0',
          userType: distributedKVStore.UserType.SAME_USER_ID
        }
      };

      this.kvManager = distributedKVStore.createKVManager(managerConfig);

      // 获取KVStore
      const options: distributedKVStore.Options = {
        createIfMissing: true,
        encrypt: false,
        backup: false,
        autoSync: true, // 开启自动同步
        kvStoreType: distributedKVStore.KVStoreType.SINGLE_VERSION
      };

      this.kvStore = await this.kvManager.getKVStore('favorites_store', options);
      this.syncStatus = '已连接';

      // 订阅数据变化
      this.subscribeDataChange();

      // 订阅设备上下线
      this.subscribeDeviceChange();

      // 加载数据
      await this.loadFavorites();

      hilog.info(0x0000, 'DistributedFavorites', '分布式存储初始化成功');
    } catch (err) {
      const error = err as BusinessError;
      hilog.error(0x0000, 'DistributedFavorites', `初始化失败: ${error.message}`);
    }
  }

  // 订阅数据变化
  subscribeDataChange() {
    if (!this.kvStore) return;

    this.kvStore.on('dataChange', distributedKVStore.SubscribeType.SUBSCRIBE_TYPE_ALL, async (data) => {
      hilog.info(0x0000, 'DistributedFavorites', `收到数据变更: ${JSON.stringify(data)}`);
      await this.loadFavorites();
    });
  }

  // 订询设备变化
  subscribeDeviceChange() {
    if (!this.kvManager) return;

    this.kvManager.on('distributedDataServiceDie', () => {
      hilog.warn(0x0000, 'DistributedFavorites', '分布式服务断开');
      this.syncStatus = '已断开';
    });
  }

  // 加载收藏列表
  async loadFavorites() {
    if (!this.kvStore) return;

    try {
      const entries = await this.kvStore.getEntries('favorite_');
      const items: FavoriteItem[] = [];

      for (const entry of entries) {
        if (entry.value) {
          try {
            const item = JSON.parse(entry.value as string) as FavoriteItem;
            items.push(item);
          } catch (e) {
            // 忽略解析失败的数据
          }
        }
      }

      // 按时间倒序排列
      items.sort((a, b) => b.addTime - a.addTime);
      this.favorites = items;
    } catch (err) {
      hilog.error(0x0000, 'DistributedFavorites', `加载失败: ${err}`);
    }
  }

  // 添加收藏
  async addFavorite() {
    if (!this.kvStore) return;

    const newItem: FavoriteItem = {
      id: `fav_${Date.now()}`,
      title: `收藏项 ${this.favorites.length + 1}`,
      url: `https://example.com/${this.favorites.length + 1}`,
      addTime: Date.now()
    };

    try {
      // 使用前缀+ID作为key,便于批量查询
      await this.kvStore.put(`favorite_${newItem.id}`, JSON.stringify(newItem));
      await this.loadFavorites();
      hilog.info(0x0000, 'DistributedFavorites', '添加收藏成功,已同步到其他设备');
    } catch (err) {
      hilog.error(0x0000, 'DistributedFavorites', `添加收藏失败: ${err}`);
    }
  }

  // 删除收藏
  async deleteFavorite(id: string) {
    if (!this.kvStore) return;

    try {
      await this.kvStore.delete(`favorite_${id}`);
      await this.loadFavorites();
    } catch (err) {
      hilog.error(0x0000, 'DistributedFavorites', `删除收藏失败: ${err}`);
    }
  }

  // 手动同步到指定设备
  async syncToDevice(deviceId: string) {
    if (!this.kvStore) return;

    try {
      await this.kvStore.sync([deviceId], distributedKVStore.SyncMode.PUSH_PULL);
      hilog.info(0x0000, 'DistributedFavorites', `已触发同步到设备: ${deviceId}`);
    } catch (err) {
      hilog.error(0x0000, 'DistributedFavorites', `同步失败: ${err}`);
    }
  }

  build() {
    Column() {
      // 标题栏
      Row() {
        Text('分布式收藏夹')
          .fontSize(24)
          .fontWeight(FontWeight.Bold)

        Blank()

        Text(this.syncStatus)
          .fontSize(12)
          .fontColor(this.syncStatus === '已连接' ? '#4CAF50' : '#FF5722')
          .padding({ left: 8, right: 8, top: 4, bottom: 4 })
          .backgroundColor(this.syncStatus === '已连接' ? '#E8F5E9' : '#FBE9E7')
          .borderRadius(12)
      }
      .width('100%')
      .padding(16)

      // 添加按钮
      Button('添加收藏(自动同步到其他设备)')
        .width('90%')
        .margin({ bottom: 16 })
        .onClick(() => this.addFavorite())

      // 收藏列表
      List({ space: 8 }) {
        ForEach(this.favorites, (item: FavoriteItem) => {
          ListItem() {
            Column() {
              Text(item.title)
                .fontSize(16)
                .fontWeight(FontWeight.Medium)

              Text(item.url)
                .fontSize(12)
                .fontColor('#666666')
                .margin({ top: 4 })

              Text(new Date(item.addTime).toLocaleString())
                .fontSize(11)
                .fontColor('#999999')
                .margin({ top: 4 })
            }
            .width('100%')
            .padding(12)
            .backgroundColor('#FFFFFF')
            .borderRadius(8)
            .gesture(
              LongPressGesture()
                .onAction(() => this.deleteFavorite(item.id))
            )
          }
        })
      }
      .padding(16)
      .layoutWeight(1)
    }
    .width('100%')
    .height('100%')
    .backgroundColor('#F5F5F5')
  }
}

关键点说明

  1. 分布式数据需要在多个设备上登录同一华为账号

  2. autoSync: true 可以自动同步,也可以手动调用 sync()

  3. 使用 on('dataChange') 监听数据变化,实现实时更新

  4. key的设计很重要,使用前缀便于批量查询


五、三大方案对比与选型

5.1 对比表格

特性

Preferences

RDB

分布式KV

数据类型

键值对(基础类型)

结构化表格数据

键值对(基础类型)

数据量

小(建议 < 几KB)

大(支持百万级)

中等(建议 < 10MB)

查询能力

仅按key查询

支持SQL查询

仅按key/前缀查询

跨设备

不支持

不支持

支持

性能

极快(内存缓存)

中等(含同步开销)

使用复杂度

适用场景

配置、开关、Token

业务数据、记录

多设备协同数据

5.2 选型决策树

遇到数据持久化需求时,可以按照下面的决策树来选型:

需要持久化数据
    │
    ├── 数据需要跨设备同步?
    │       ├── 是 → 分布式KV
    │       └── 否 ↓
    │
    ├── 数据结构复杂?需要查询/排序/筛选?
    │       ├── 是 → RDB
    │       └── 否 ↓
    │
    ├── 数据量大?(超过几十KB)
    │       ├── 是 → RDB
    │       └── 否 ↓
    │
    └── Preferences ✅

简单总结

  • 配置类数据 → Preferences(最简单)

  • 业务数据 → RDB(功能最强)

  • 跨设备数据 → 分布式KV(鸿蒙特色)


六、常见坑与最佳实践

6.1 Preferences常见坑

问题

原因

解决方案

数据丢失

忘记调用 flush()

每次写入后都调用 flush()

内存溢出

存储了大图片或长文本

大数据用文件或RDB存储

并发问题

多线程同时读写

使用同一个Preferences实例

最佳实践

// 好的做法:封装工具类
class PreferencesUtil {
  private static store: preferences.Preferences | null = null;

  static async init(context: Context) {
    this.store = await preferences.getPreferences(context, 'appSettings');
  }

  static async set(key: string, value: preferences.ValueType) {
    if (!this.store) return;
    await this.store.put(key, value);
    await this.store.flush(); // 立即持久化
  }

  static async get<T>(key: string, defaultValue: T): Promise<T> {
    if (!this.store) return defaultValue;
    return (await this.store.get(key, defaultValue)) as T;
  }
}

6.2 RDB常见坑

问题

原因

解决方案

ResultSet泄漏

忘记关闭ResultSet

使用完后调用 close()

主线程卡顿

大量数据操作在主线程

异步操作,或用Worker线程

升级问题

表结构变更后崩溃

使用版本号+onUpgrade处理

最佳实践

// 使用try-finally确保ResultSet关闭
async queryData(): Promise<TodoItem[]> {
  const predicates = new relationalStore.RdbPredicates('todos');
  const resultSet = await this.store.query(predicates, ['id', 'title', 'completed']);

  try {
    const result: TodoItem[] = [];
    while (resultSet.goToNextRow()) {
      // 处理数据...
    }
    return result;
  } finally {
    resultSet.close(); // 确保关闭
  }
}

6.3 分布式KV常见坑

问题

原因

解决方案

同步不生效

未登录华为账号

引导用户登录

数据冲突

多设备同时修改同一key

使用时间戳作为冲突解决策略

权限问题

未配置分布式权限

在module.json5中配置

module.json5权限配置

{
  "requestPermissions": [
    {
      "name": "ohos.permission.DISTRIBUTED_DATASYNC"
    }
  ]
}

七、总结

今天我们系统学习了鸿蒙的三大数据持久化方案:

  1. Preferences:轻量级首选,适合配置、开关等简单数据,使用最简单

  2. RDB:关系型数据库,适合业务数据、聊天记录等结构化数据,功能最强

  3. 分布式KV:鸿蒙特色,适合跨设备同步的协同数据

选型口诀

  • 配置开关用 Preferences

  • 业务数据用 RDB

  • 跨设备用 分布式KV

掌握了这三板斧,你的App数据再也不会"失忆"了!下一篇我们将学习文件管理与沙箱机制,敬请期待。


系列文章推荐

序号

文章标题

主题

01

鸿蒙NEXT开发实战系列开篇词

系列介绍

02

鸿蒙开发环境搭建与Hello World

入门基础

03

ArkTS语法快速上手

语言基础

04

ArkUI组件开发基础

UI基础

05

布局系统详解

布局

06

状态管理深入理解

状态管理

07

列表与懒加载

列表组件

08

页面路由与导航

路由导航

09

组件生命周期详解

生命周期

10

自定义组件开发

组件化

11

动画开发实战

动画

12

手势处理与交互

手势交互

13

网络请求与数据加载

网络

14

JSON解析与数据模型

数据处理

15

应用上下文与Ability

应用模型

16

通知与后台任务

后台

17

权限管理最佳实践

权限

18

多线程与并发编程

并发

19

性能优化实战指南

性能

20

网络篇-网络请求与数据加载

网络进阶

21

数据持久化三板斧(本文)

数据存储


标签#Preferences #RDB #分布式数据 #鸿蒙存储 #数据持久化 #ArkTS #HarmonyOS


💡 你觉得这篇文章有帮助吗? 欢迎点赞、收藏、评论,你的支持是我持续创作的动力!

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐