鸿蒙开发中,如何存储搜索历史记录,关闭鸿蒙APP再次启动还能拿到数据那种?

鸿蒙开发中,如何存储搜索历史记录,关闭鸿蒙APP再次启动还能拿到数据那种?

阅读 534
avatarAI BotBETA

在鸿蒙(HarmonyOS)应用开发中,要实现搜索历史记录的持久化存储(应用关闭后仍可读取),推荐使用 轻量级偏好数据库(Preferences)关系型数据库(RelationalStore)。以下是最常用的轻量级存储方案:


方案:使用 Preferences 存储搜索历史

核心步骤:

  1. 初始化 Preferences 实例
    AbilityAbilitySlice 中获取 Preferences 对象:

    // 在 AbilitySlice 中
    String prefName = "search_history"; // 数据库文件名
    Preferences preferences = getPreferences(prefName);
  2. 存储历史记录(以字符串数组为例)
    将搜索记录转换为 Set<String> 存储:

    // 假设 historyList 是 List<String> 类型的历史记录
    Set<String> historySet = new HashSet<>(historyList);
    preferences.putStringSet("history_key", historySet)
               .flush(); // 立即写入磁盘
  3. 读取历史记录
    应用重启时读取数据:

    Set<String> historySet = preferences.getStringSet("history_key", new HashSet<>());
    List<String> loadedHistory = new ArrayList<>(historySet); // 转换为 List
  4. 控制历史记录数量(可选)
    添加新记录时限制最大数量:

    // 保留最近 10 条记录
    if (loadedHistory.size() >= 10) {
        loadedHistory.remove(0); // 移除最旧记录
    }
    loadedHistory.add(newSearchTerm);

关键细节说明:

  1. 存储位置
    Preferences 数据存储在应用沙箱内 (/data/app/.../database/),应用卸载时自动清除。
  2. 异步写入
    使用 flush()flushAsync()(推荐)确保数据持久化:

    preferences.putStringSet("key", data)
               .flushAsync()
               .thenAccept(result -> {
                   if (result) {
                       HiLog.info("存储成功");
                   }
               });
  3. 数据类型限制
    Preferences 支持:StringbooleanintfloatlongSet<String>
  4. 多设备同步(需额外配置)
    若需跨设备同步历史记录,使用 分布式数据管理 (DistributedDataManager),但需申请权限和配置分布式能力。

完整流程示例:

public class MainAbilitySlice extends AbilitySlice {
    private Preferences preferences;
    private List<String> searchHistory = new ArrayList<>();

    @Override
    public void onStart(Intent intent) {
        // 1. 初始化 Preferences
        preferences = getPreferences("search_db");
        
        // 2. 读取历史记录
        loadHistory();
        
        // 3. 模拟新增搜索
        addSearchTerm("鸿蒙开发");
        addSearchTerm("持久化存储");
    }

    private void loadHistory() {
        Set<String> historySet = preferences.getStringSet("history", Collections.emptySet());
        searchHistory = new ArrayList<>(historySet);
    }

    private void addSearchTerm(String term) {
        // 去重 & 限制数量
        searchHistory.remove(term);
        searchHistory.add(term);
        if (searchHistory.size() > 10) {
            searchHistory.remove(0);
        }
        
        // 保存到 Preferences
        preferences.putStringSet("history", new HashSet<>(searchHistory))
                   .flushAsync();
    }
}

备选方案:关系型数据库 (RelationalStore)

若历史记录需要复杂查询(如按时间排序、关联用户信息),使用关系型数据库:

// 1. 创建数据库
StoreConfig config = StoreConfig.newDefaultConfig("history.db");
RelationalStoreHelper helper = RelationalStoreHelper.getInstance(context, config);

// 2. 建表
String sql = "CREATE TABLE IF NOT EXISTS search_history (id INTEGER PRIMARY KEY, term TEXT, time TIMESTAMP)";
helper.executeSql(sql);

// 3. 插入数据
ValuesBucket values = new ValuesBucket();
values.putString("term", "鸿蒙");
values.putLong("time", System.currentTimeMillis());
helper.insert("search_history", values);

总结建议:

  • 轻量数据(<10KB):优先用 Preferences,简单高效
  • 复杂数据:选 RelationalStoreObjectStore
  • 跨设备同步:结合 DistributedDataManager

两种方案均能保证应用关闭后数据不丢失,按实际需求选择即可。

2 个回答
  1. 使用 KVStore:引入 @ohos.data.kvStore 模块。通过 KvStore.create 创建实例,将搜索历史记录以键值对形式存储,键可设为固定标识如 searchHistory,值为包含历史记录的数组。使用 put 方法存储,get 方法读取,重启 APP 时即可获取数据。
  2. 关系型数据库(RelationalStore):利用 @ohos.data.relationalStore。先创建表结构,如包含 id(自增主键)、searchContent(搜索内容)、searchTime(搜索时间)字段。通过 executeSql 执行插入语句存储记录,查询语句获取数据,保证重启 APP 数据不丢失。
  3. 偏好设置(Preferences):导入 @ohos.data.preferences。用 create 方法创建偏好设置实例,将搜索历史记录序列化为字符串存储在偏好设置中,如 put('searchHistory', JSON.stringify(historyArray)),获取时反序列化 JSON.parse(await get('searchHistory'))
  4. 分布式数据管理(可选):若需跨设备同步搜索历史,使用 @ohos.data.distributedData。通过 DistributedData.create 创建分布式数据对象,按上述类似方式存储和获取数据,可保证不同设备上 APP 重启都能获取最新历史记录。
新手上路,请多包涵

【解决方案】
1.使用getPreferencesSync()方法获取Preferences实例。
2.自定义set()方法,使用putSync()方法将数据写入Preferences实例中。
3.自定义get()方法,使用getSync()方法获取数据,即指定键对应的值。
4.调用set()和get()方法,来实现数据存取。

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

class MyObj{
  name: string = 'aa';
  age: number = 10;
}
const context: common.Context = AppStorage.get('context') as common.Context;
class MyPreference{

  static instance: preferences.Preferences = preferences.getPreferencesSync(context ,{ name: 'test' });

  static setString(key: string, value: string): void{
    MyPreference.instance.putSync(key, value);
    MyPreference.instance.flushSync();
  }

  static getString(key: string, defaultValue: string = ''): string{
    return MyPreference.instance.getSync(key, defaultValue) as string;
  }

  static setObject(key: string, value: object): void{
    MyPreference.instance.putSync(key, value);
    MyPreference.instance.flushSync();
  }

  static getObject<T extends object>(key: string, defaultValue: T = new Object as T): T{
    return MyPreference.instance.getSync(key, defaultValue) as T;
  }
}

@Entry
@Component
struct Index{

  @State value: string = '123';
  @State obj: MyObj = new MyObj();

  build() {
    Column(){
      Text(this.value)
        .onClick(() => {
          this.value += this.value.length + 1;
        })

      Text(JSON.stringify(this.obj))
        .onClick(() => {
          this.obj.age ++;
        })

      Button('保存数据')
        .onClick(() => {
          MyPreference.setString('key', this.value);
          MyPreference.setObject('key_object', this.obj);
        })

      Button('获取数据')
        .onClick(() => {
          this.value = MyPreference.getString('key', this.value);
          this.obj = MyPreference.getObject('key_object', this.obj);
        })
    }
    .width('100%')
    .height('100%')
    .borderRadius(15)
  }
}

【约束与限制】

  • Key键为string类型,要求非空且长度不超过1024个字节。
  • 如果Value值为string类型,请使用UTF-8编码格式,可以为空,不为空时长度不超过16MB。
  • 当调用removePreferencesFromCache或者deletePreferences后,订阅的数据变更会主动取消订阅,重新getPreferences后需要重新订阅数据变更。
  • 不允许deletePreferences与其他接口多线程、多进程并发调用,否则可能会发生不可预期行为。
  • 不支持数据加密存储。如果需要进行数据加密,应用应该先将数据进行加密,然后将密文通过Uint8Array类型存储到Preferences中。
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进