HarmonyOS鸿蒙Next中求解,应用升级后、桌面卡片数据丢失

HarmonyOS鸿蒙Next中求解,应用升级后、桌面卡片数据丢失 卡片代码如下,已经持久化了,手机重启后数据也不会丢,但是进行版本升级后(比如1.0.0->1.0.1),卡片数据却没了

/*
 * Copyright (c) 2024 懒猫Record. All rights reserved.
 */

import { formBindingData, FormExtensionAbility, formInfo, formProvider } from '@kit.FormKit';
import { Want } from '@kit.AbilityKit';
import { preferences } from '@kit.ArkData';
import { ItemRecordDatabase } from '../common/service/ItemRecordDatabase';
import { ItemRecord } from '../common/model/ItemRecordModel';

/**
 * 物品卡片Ability
 * 使用 DataPreferences 进行数据持久化(参考 myHistory 的存储方式)
 */
export default class ItemWidgetAbility extends FormExtensionAbility {
  /**
   * 添加卡片
   */
  onAddForm(want: Want) {
    const formId = want.parameters!['ohos.extra.param.key.form_identity'].toString();
    console.info(`ItemWidget onAddForm: formId=${formId}`);

    let options: preferences.Options = {
      name: 'itemWidgets'
    };
    preferences.removePreferencesFromCacheSync(this.context, options);
    let dataPreferences = preferences.getPreferencesSync(this.context, options);

    // 1. 更新 formIds 列表
    let preFormIdsArray: Array<string> = JSON.parse(dataPreferences.getSync('formIds', '[]').toString());
    if (preFormIdsArray && preFormIdsArray.indexOf(formId) == -1) {
      preFormIdsArray.push(formId);
    }
    dataPreferences.putSync('formIds', JSON.stringify(preFormIdsArray));

    // 2. 尝试加载该卡片的数据
    const widgetKey = `widget_${formId}`;
    let widgetDataStr = dataPreferences.getSync(widgetKey, '').toString();
    
    let widgetData: Record<string, ESObject>;
    
    if (widgetDataStr) {
      // 找到保存的数据
      widgetData = JSON.parse(widgetDataStr) as Record<string, ESObject>;
      console.info(`从 preferences 加载卡片数据: formId=${formId}`);
    } else {
      // 没有保存的数据,使用默认数据
      widgetData = {
        'formId': formId,
        'itemId': '',
        'itemName': '点击选择物品',
        'categoryName': '未设置',
        'specQuantity': 0,
        'purchaseCount': 1,
        'totalQuantity': 0,
        'remainingQuantity': 0,
        'unit': '',
        'usagePercentage': 0,
        'price': 0,
        'needSelectItem': true
      };
      
      // 保存默认数据
      dataPreferences.putSync(widgetKey, JSON.stringify(widgetData));
      console.info(`首次创建卡片,使用默认数据: formId=${formId}`);
    }

    // 3. 持久化数据
    dataPreferences.flush();

    return formBindingData.createFormBindingData(widgetData);
  }


  /**
   * 卡片更新(系统定时刷新时调用)
   * 说明:
   * 1. 系统会定时调用此方法(每30分钟一次)
   * 2. autoDeductDailyUsage() 内部已调用 refreshItemWidgets() 刷新所有相关卡片的UI
   * 3. 因此这里不需要手动调用 formProvider.updateForm()
   */
  onUpdateForm(formId: string) {
    console.info(`[卡片刷新] 系统触发定时刷新 formId=${formId}`);

    try {
      const database = ItemRecordDatabase.getInstance();
      database.initialize(this.context).then(() => {
        // 执行每日自动扣减余量(内部会自动刷新所有卡片UI)
        const updateCount = database.autoDeductDailyUsage();
        console.info(`[卡片刷新] 完成:更新了 ${updateCount} 个物品,所有关联卡片UI已同步刷新`);
      })
    } catch (error) {
      console.error('[卡片刷新] 失败:', error);
    }
  }

  /**
   * 卡片删除
   */
  onRemoveForm(formId: string) {
    console.info(`ItemWidget onRemoveForm: ${formId}`);

    let options: preferences.Options = {
      name: 'itemWidgets'
    };
    preferences.removePreferencesFromCacheSync(this.context, options);
    let dataPreferences = preferences.getPreferencesSync(this.context, options);

    // 1. 从 formIds 列表中移除
    let preFormIdsArray: Array<string> = JSON.parse(dataPreferences.getSync('formIds', '[]').toString());
    if (preFormIdsArray && preFormIdsArray.indexOf(formId) !== -1) {
      const index = preFormIdsArray.indexOf(formId);
      preFormIdsArray.splice(index, 1);
    }
    dataPreferences.putSync('formIds', JSON.stringify(preFormIdsArray));

    // 2. 删除该卡片的数据
    const widgetKey = `widget_${formId}`;
    dataPreferences.deleteSync(widgetKey);

    // 3. 持久化更改
    dataPreferences.flush();

    console.info(`卡片数据已删除: formId=${formId}`);
  }

  /**
   * 卡片事件
   */
  onFormEvent(formId: string, message: string) {
    console.info(`ItemWidget onFormEvent: formId=${formId}, message=${message}`);
  }

  /**
   * 转为普通卡片
   */
  onCastToNormalForm(formId: string) {
    console.info(`ItemWidget onCastToNormalForm: ${formId}`);
  }
}

更多关于HarmonyOS鸿蒙Next中求解,应用升级后、桌面卡片数据丢失的实战教程也可以访问 https://www.itying.com/category-93-b0.html

3 回复

沙盒文件还在吗?

更多关于HarmonyOS鸿蒙Next中求解,应用升级后、桌面卡片数据丢失的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


在HarmonyOS Next中,应用升级后桌面卡片数据丢失通常是由于系统升级时卡片缓存机制重置或应用数据迁移不完整导致。卡片数据依赖应用沙盒存储,升级过程中若未正确保留持久化数据,会触发卡片重建。开发者需确保在应用升级逻辑中维护卡片状态持久化,使用HarmonyOS提供的卡片数据恢复机制。系统级卡片管理服务在升级时可能清空临时缓存,因此应用应实现onRestoreForm接口来恢复数据。

在HarmonyOS Next中,应用升级后桌面卡片数据丢失的问题通常与数据持久化方式有关。从代码看,您使用了preferences存储卡片数据,但每次onAddForm都调用removePreferencesFromCacheSync,这可能在升级时清除了缓存导致数据丢失。

建议检查:

  1. 应用升级时preferences文件是否被系统重置
  2. 确保onAddForm中不要频繁调用removePreferencesFromCacheSync
  3. 考虑使用数据库或文件系统进行更可靠的数据持久化

可以尝试在应用升级时实现数据迁移逻辑,确保卡片数据从旧版本正确迁移到新版本。

回到顶部