开发中使用——鸿蒙本地存储之收藏功能

文章目录


开发中使用------鸿蒙本地存储之收藏功能

一、背景

一个本地应用,做一个收藏功能,要求收藏的内容,下次打开App的时候,还可以看到。

二、思路

本地缓存

  • 文件缓存:使用轻量级缓存SharedPreferences
  • 数据库缓存:sqlLite(后续会进行展开介绍)

三、方案一

轻量级缓存SharedPreferences的实现

首先要解决下面这几个问题,什么时候存、什么时候取,如何存,以及应用内数据如何同步的问题。

1.准备工作

我们需要有一个管理缓存的单例类,处理存、取、添加、修改、删除等操作。所以大概情况下,我们要先有下面这样一个结构的类,用来管理这一堆事情。

复制代码
import { common } from '@kit.AbilityKit'
import { preferences } from '@kit.ArkData'
import { Country } from './DataModel'

/**
 * 收藏数据管理
 */
export class CollectDataManager {
  private static instance: CollectDataManager;
  public  collectItems: Array<Country> = []
  private  myStore:string = 'com.silence.flagCard';
  private itemsKey: string = 'flagCard'
  private static context: common.UIAbilityContext; // 应用上下文

  // 私有构造函数
  private constructor() {}

  // 初始化上下文(需在应用启动时调用)
  public static init(context: common.UIAbilityContext): void {
    CollectDataManager.context = context;
  }

  // 获取单例实例
  public static getInstance(): CollectDataManager {
    if (!CollectDataManager.instance) {
      if (!CollectDataManager.context) {
        throw new Error('Context not initialized! Call PreferencesUtil.init() first.');
      }
      CollectDataManager.instance = new CollectDataManager();
    }
    return CollectDataManager.instance;
  }
  
  /**
   * 加载缓存数据
   */
  public async loadData() {}

  /**
   * 加载缓存数据
   */
  public async loadData() {
    try {
      let pref = await preferences.getPreferences(CollectDataManager.context, this.myStore);
      let itemsJson = await pref.get(this.itemsKey, '');
      let itemsData = JSON.parse(itemsJson.toString()) as Array<Country>
      this.collectItems = itemsData;

    } catch (error) {
      console.error('加载数据失败:', error)
      this.collectItems = []
    }
  }

  /**
   * 保存缓存数据
   */
  async saveData() {
    try {
      let itemsJson = JSON.stringify(this.collectItems)
      let pref = await preferences.getPreferences(CollectDataManager.context, this.myStore);
      await pref.put(this.itemsKey, itemsJson)
      await pref.flush()

    } catch (error) {
      console.error('保存数据失败:', error)
    }
  }

  /**
   * 更新数据
   * @param item
   */
  updateItem(item: Country) {}

  /**
   * 删除数据
   * @param id
   */
  deleteItem(id: number) {}

  /**
   * 获取所有收藏数据
   * @returns
   */
  getAllItems(): Array<Country> {
    return this.collectItems
  }

  /**
   * 通过id获取收藏数据item
   * @returns
   */
  getItemById(id: number): Country | undefined{
    return this.collectItems.find(item => item.id == id)
  }
}

2.解决什么时候存

应用销毁之前,要将收藏的数据存到缓存文件中。我是建议在入口EntryAbility中onDestroy()方法中存储数据。

复制代码
  onDestroy(): void {
    hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onDestroy');

    /// 保存数据
    CollectDataManager.getInstance().saveData();
  }

3.解决什么时候取

应用打开的时候,要将缓存的数据取出来。在收藏页面展示出来。我是建议在入口EntryAbility中onCreate()中初始化数据管理的单例类和获取数据。

复制代码
 onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
    this.context.getApplicationContext().setColorMode(ConfigurationConstant.ColorMode.COLOR_MODE_NOT_SET);
    hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onCreate');

    /// 初始化轻量级缓存
    CollectDataManager.init(this.context);
    CollectDataManager.getInstance().loadData();
  }

4.如何存

这里其实设计三个问题,添加数据、修改数据、删除数据。

  • 添加数据

    复制代码
    /**
     * 添加数据
     * @param item
     */
    addItem(item: Country) {
      /// 需要去重处理
      if(this.getItemById(item.id)){
        return;
      }
    
      this.collectItems.push(item)
      this.saveData()
    }
  • 修改数据

    复制代码
    /**
     * 更新数据
     * @param item
     */
    updateItem(item: Country) {
      // 判断是否存在
      const index = this.collectItems.findIndex(i => i.id === item.id)
      if (index !== -1) {
        this.collectItems[index] = item
        this.saveData()
      }
    }
  • 删除数据

    复制代码
    /**
     * 删除数据
     * @param id
     */
    deleteItem(id: number) {
      // 判断是否存在
      const index = this.collectItems.findIndex(i => i.id === id)
      if (index !== -1) {
        this.collectItems.splice(index, 1)
        this.saveData()
      }
    }

5.数据如何同步

需要借助修饰词 @ObservedV2 对类进行装饰,对需要数据变化,全局UI变化的collectItems使用@Trace进行装饰。修改如下。

复制代码
/**
 * 收藏数据管理
 */
@ObservedV2
export class CollectDataManager {
  private static instance: CollectDataManager;

  @Trace
  public  collectItems: Array<Country> = []

......

6.如何使用

  • 获取这个收藏列表

    /**

    • 我的收藏页面
      */
      @Component
      export struct CollectPage {
      // 获取收藏列表
      @State myCollectItems:Country[] = CollectDataManager.getInstance().collectItems;

    ......

  • 添加/删除收藏列表的某一项数据
    先验证是否已经收藏,这个也是显示收藏按钮状态的一个状态变量。然后在用户点击收藏按钮时候,判断是否进行收藏或者取消收藏。

    复制代码
       /// 验证是已经收藏
        this.isFavorite = CollectDataManager.getInstance().getItemById(this.country.id) != undefined;
    
        if(this.isFavorite){
          CollectDataManager.getInstance().deleteItem(this.country.id);
        }else{
          CollectDataManager.getInstance().addItem(this.country);
        }

7.展示效果

相关推荐
qq_316837756 小时前
spring cloud 同一服务多实例 websocket跨实例无法共享Session 的解决
java·websocket·spring cloud
草莓熊Lotso6 小时前
《算法闯关指南:优选算法--滑动窗口》--14找到字符串中所有字母异位词
java·linux·开发语言·c++·算法·java-ee
青云交6 小时前
Java 大视界 -- 基于 Java 的大数据实时流处理在金融高频交易数据分析中的应用
java·大数据·量化交易·异常检测·apache flink·实时流处理·金融高频交易
hhhhhshiyishi6 小时前
WLB公司内推|招联金融2026届校招|18薪
java·算法·机器学习·金融·求职招聘
韩立学长6 小时前
【开题答辩实录分享】以《城市网约车服务预约与管理小程序的设计与实现》为例进行答辩实录分享
java·小程序·选题
yics.6 小时前
多线程——单例模式
java·单例模式·多线程·线程安全
别惹CC7 小时前
Spring AI 进阶之路03:集成RAG构建高效知识库
java·人工智能·spring
万少7 小时前
十行代码 带你极速接入鸿蒙6新特性 - 应用内打分评价
前端·harmonyos
舒一笑7 小时前
PandaCoder 1.1.8 发布:中文开发者的智能编码助手全面升级
java·后端·intellij idea
这周也會开心7 小时前
Spring-MVC
java·spring·mvc