HarmonyOS 鸿蒙Next kvstore 保存和获取数据异常

HarmonyOS 鸿蒙Next kvstore 保存和获取数据异常

import { distributedKVStore } from '@kit.ArkData';
import { bundleManager } from '@kit.AbilityKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
import { KVStoreType } from '../viewmodel/KVStoreType';
import { BusinessError } from '@kit.BasicServicesKit';

// 添加接口定义
interface KVStoreService {
  getKVStore(): Promise<KVStore>;
}

// 添加配置接口定义
interface KVManagerConfig {
  context: Context;
  bundleName: string;
}

interface KVStoreOptions {
  createIfMissing: boolean;
  backup: boolean;
  autoSync: boolean;
  kvStoreType: distributedKVStore.KVStoreType;
  encrypt: boolean;
  securityLevel: distributedKVStore.SecurityLevel;
}

// 导出 KVStore 类以便其他文件可以使用其类型
interface GeneratedObjectLiteralInterface_1 {
  code: string | number;
  message: string;
  stack: string;
}

export class KVStore {
  private static instance: KVStore | null = null;
  private static initializationPromise: Promise<void> | null = null;
  private kvManager: distributedKVStore.KVManager | undefined = undefined;
  private context = getContext(this);
  private kvStore: distributedKVStore.SingleKVStore | undefined = undefined;
  private bundleName: string = '';
  private isInitialized: boolean = false;

  // 私有构造函数
  private constructor(encrypt: boolean, securityLevel: distributedKVStore.SecurityLevel) {
    this.initKVStore(encrypt, securityLevel);
  }

  // 获取单例实例的静态方法
  public static async getInstance(encrypt: boolean = false,
    securityLevel: distributedKVStore.SecurityLevel = distributedKVStore.SecurityLevel.S1): Promise<KVStore> {
    if (!KVStore.instance) {
      KVStore.instance = new KVStore(encrypt, securityLevel);
      // 等待初始化完成
      if (!KVStore.initializationPromise) {
        KVStore.initializationPromise = KVStore.instance.initKVStore(encrypt, securityLevel);
      }
      await KVStore.initializationPromise;
    }
    return KVStore.instance;
  }

  // 添加数据变化监听
  async subscribeKVStore() {
    if (!this.kvStore) {
      return;
    }
    try {
      this.kvStore.on('dataChange', distributedKVStore.SubscribeType.SUBSCRIBE_TYPE_ALL, (data) => {
        hilog.info(0x0000, 'KVStore', `Data changed: ${JSON.stringify(data)}`);
        // 这里可以触发UI更新
      });
    } catch (error) {
      hilog.error(0x0000, 'KVStore', `Failed to subscribe: ${error}`);
    }
  }

  // 初始化 KVStore
  private async initKVStore(encrypt: boolean, securityLevel: distributedKVStore.SecurityLevel): Promise<void> {
    if (this.isInitialized) {
      return;
    }

    try {
      const bundleFlags = bundleManager.BundleFlag.GET_BUNDLE_INFO_DEFAULT;
      const bundleInfo = await bundleManager.getBundleInfoForSelf(bundleFlags);
      this.bundleName = bundleInfo.name;

      if (!this.bundleName) {
        throw new Error('Bundle name is empty');
      }

      const kvManagerConfig: KVManagerConfig = {
        context: this.context,
        bundleName: this.bundleName
      };

      this.kvManager = distributedKVStore.createKVManager(kvManagerConfig);

      const options: KVStoreOptions = {
        createIfMissing: true,
        backup: false,
        autoSync: false,
        kvStoreType: distributedKVStore.KVStoreType.SINGLE_VERSION,
        encrypt: encrypt,
        securityLevel: securityLevel
      };

      this.kvStore = await new Promise((resolve, reject) => {
        this.kvManager?.getKVStore<distributedKVStore.SingleKVStore>(
          `${securityLevel}${JSON.stringify(encrypt)}`,
          options,
          (err, store) => {
            if (err) {
              reject(err);
              return;
            }
            resolve(store);
          }
        );
      });

      this.isInitialized = true;
    } catch (error) {
      hilog.error(0x0000, 'KVStore', `Failed to initialize KVStore: ${error}`);
      throw Error('KVStore not initialized');
    }
  }

  // 确保 KVStore 已初始化
  private async ensureInitialized(): Promise<void> {
    if (!this.isInitialized) {
      await this.initKVStore(false, distributedKVStore.SecurityLevel.S1);
    }
  }

  async put(key: string, value: Uint8Array | string | number | boolean) {
    await this.ensureInitialized();

    return new Promise<void>((resolve, reject) => {
      try {
        if (!this.kvStore) {
          reject(new Error('KVStore not initialized'));
          return;
        }

        if (!key || key.trim() === '') {
          reject(new Error('Key cannot be empty'));
          return;
        }

        // 确保值是字符串类型
        let valueToStore: string;
        try {
          if (value === undefined || value === null) {
            reject(new Error('Value cannot be null or undefined'));
            return;
          }

          if (typeof value === 'object') {
            valueToStore = JSON.stringify(value);
          } else {
            valueToStore = String(value);
          }

          if (!valueToStore) {
            reject(new Error('Failed to convert value to string'));
            return;
          }
        } catch (error) {
          hilog.error(0x0000, 'KVStore', `Error converting value to string: ${error}`);
          reject(error);
          return;
        }

        // 添加日志记录
        hilog.info(0x0000, 'KVStore', `Attempting to put - Key: ${key}, Value: ${valueToStore}`);

        // 使用 try-catch 包装 put 操作
        try {
          this.kvStore.put(key, valueToStore, (err) => {
            // 检查错误对象的完整性
            if (err) {
              const errorInfo: GeneratedObjectLiteralInterface_1 = {
                code: err.code || 'NO_CODE',
                message: err.message || 'NO_MESSAGE',
                stack: err.stack || 'NO_STACK'
              };
              hilog.error(0x0000, 'KVStore', `Put operation failed with error: ${JSON.stringify(errorInfo)}`);
              
              // 如果是空错误对象(code和message都为空),我们认为这是成功的情况
              if (!err.code && !err.message) {
                hilog.info(0x0000, 'KVStore', `Empty error object received, treating as success for key: ${key}`);
                resolve();
                return;
              }
              
              reject(new Error(`Put operation failed: ${err.message || 'Unknown error'}`));
              return;
            }

            hilog.info(0x0000, 'KVStore', `Successfully put data for key: ${key}`);
            resolve();
          });
        } catch (putError) {
          hilog.error(0x0000, 'KVStore', `Exception during put operation: ${putError}`);
          reject(putError);
        }
      } catch (error) {
        hilog.error(0x0000, 'KVStore', `Error in put operation: ${error}`);
        reject(error);
      }
    });
  }

  async delete(key: string) {
    await this.ensureInitialized();
    return new Promise<void>((resolve, reject) => {
      this.kvStore!.delete(key, (err) => {
        if (err) {
          hilog.error(0x0000, 'KVStore', `Failed to delete data. Code:${err.code},message:${err.message}`);
          reject(err);
          return;
        }
        hilog.info(0x0000, 'KVStore', 'Succeeded in deleting data.');
        resolve();
      });
    });
  }

  async get(key: string): Promise<KVStoreType> {
    await this.ensureInitialized();

    return new Promise<KVStoreType>((resolve, reject) => {
      if (!this.kvStore) {
        reject(new Error('KVStore not initialized'));
        return;
      }

      this.kvStore.get(key, (err: BusinessError, data: boolean | string | number | Uint8Array) => {
        if (err) {
          hilog.error(0x0000, 'KVStore', `Failed to get data. Code:${err.code},message:${err.message}`);
          // 如果获取失败,返回一个默认值
          resolve(new KVStoreType(key, "undefined", "undefined"));
          return;
        }

        // 确定数据类型
        let dataType: string = typeof data;
        if (dataType === 'object' && data instanceof Uint8Array) {
          dataType = 'Uint8Array';
        }

        // 创建并返回 KVStoreType 实例
        const kvStoreType = new KVStoreType(key, data, dataType);
        hilog.info(0x0000, 'KVStore', `Successfully got data: ${JSON.stringify(kvStoreType)}`);
        resolve(kvStoreType);
      });
    });
  }

  async getAll(): Promise<KVStoreType[]> {
    try {
      await this.ensureInitialized();
      
      if (!this.kvStore) {
        hilog.error(0x0000, 'KVStore', 'KVStore is not initialized');
        return [];
      }

      // 获取条目的 Promise
      const entriesPromise = new Promise<distributedKVStore.Entry[]>((resolve, reject) => {
        this.kvStore!.getEntries(new distributedKVStore.Query(), (err, entries) => {
          // err 为 undefined 表示操作成功
          if (err === undefined) {
            if (!entries) {
              hilog.error(0x0000, 'KVStore', 'Operation succeeded but entries is undefined');
              resolve([]);
              return;
            }
            hilog.info(0x0000, 'KVStore', `Operation succeeded, got ${entries.length} entries`);
            resolve(entries);
            return;
          }

          if(err){
            hilog.info(0x0000, 'KVStore', `Operation succeeded, got ${entries.length} entries`);
            resolve(entries);
            return;
          }
          // err 不为 undefined 表示操作失败
          hilog.error(0x0000, 'KVStore', `Failed to get entries: ${JSON.stringify(err)}`);
          reject(err);
        });
      });

      const entries = await entriesPromise;
      let allKVStore: KVStoreType[] = [];

      if (!entries || entries.length === 0) {
        hilog.info(0x0000, 'KVStore', 'No entries found');
        return [];
      }

      for (const entry of entries) {
        try {
          if (!entry || !entry.value || entry.value.value === undefined) {
            hilog.error(0x0000, 'KVStore', `Invalid entry: ${JSON.stringify(entry)}`);
            continue;
          }

          let type: string = typeof entry.value.value;
          if (type === 'object') {
            type = 'Uint8Array';
          }
          
          hilog.info(0x0000, 'KVStore', `Processing entry - Key: ${entry.key}, Type: ${type}`);
          
          let kvStoreType = new KVStoreType(entry.key, entry.value.value, type);
          allKVStore.push(kvStoreType);
          hilog.info(0x0000, 'KVStore', `Successfully processed entry: ${entry.key}`);
        } catch (error) {
          hilog.error(0x0000, 'KVStore', `Error processing entry ${entry?.key}: ${error}`);
          continue;
        }
      }

      hilog.info(0x0000, 'KVStore', `Successfully processed ${allKVStore.length} items`);
      return allKVStore;
    } catch (error) {
      hilog.error(0x0000, 'KVStore', `Error in getAll: ${error}`);
      return [];
    }
  }
}

// 定义服务类
class KVStoreServiceImpl implements KVStoreService {
  private static instance: KVStoreServiceImpl | null = null;
  private kvStoreInstance: Promise<KVStore> | null = null;

  private constructor() {}

  public static getInstance(): KVStoreServiceImpl {
    if (!KVStoreServiceImpl.instance) {
      KVStoreServiceImpl.instance = new KVStoreServiceImpl();
    }
    return KVStoreServiceImpl.instance;
  }

  async getKVStore(): Promise<KVStore> {
    if (!this.kvStoreInstance) {
      this.kvStoreInstance = KVStore.getInstance(false, distributedKVStore.SecurityLevel.S1);
    }
    return await this.kvStoreInstance;
  }
}

// 导出默认实例
export default KVStoreServiceImpl.getInstance();

更多关于HarmonyOS 鸿蒙Next kvstore 保存和获取数据异常的实战教程也可以访问 https://www.itying.com/category-93-b0.html

6 回复
// 定义待办项的接口
export interface INextActionItem {
  id: string;
  title: string;
  datetime: string;
  needRemind: boolean;
  isCompleted: boolean;
}

// 待办类实现该接口 @Observed export class NextActionItem implements INextActionItem { id: string = ‘’; title: string = ‘’; datetime: string = ‘’; needRemind: boolean = false; isCompleted: boolean = false;

constructor(id: string, title: string, datetime: string, needRemind: boolean, isCompleted: boolean) { this.id = id; this.title = title; this.datetime = datetime; this.needRemind = needRemind; this.isCompleted = isCompleted; } }<button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 8px; right: 8px; font-size: 14px;">复制</button>

更多关于HarmonyOS 鸿蒙Next kvstore 保存和获取数据异常的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


想要将上述代码问题复现,发现this.todos报错,NextActionItem无定义,请提供完整的工程代码,谢谢!根据报错日志应该是JS调用栈崩溃问题,从日志中发现在KVstore模块中发生崩溃,通过堆栈轨迹分析可以定位是哪个函数调用出现崩溃,可以参考https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/ide-release-app-stack-analysis-V5得到崩溃的函数信息,补充上述信息后,再进行进一步分析定位。

期待你的回复

你好,NextActionItem的定义代码我已经补充到下一条评论中

KVStoreType

export class KVStoreType {
  public key: string;
  public value: Uint8Array | string | number | boolean;
  public type: string;

constructor(key: string, value: Uint8Array | string | number | boolean, type: string) { this.key = key; this.value = value; this.type = type; } }<button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 8px; right: 8px; font-size: 14px;">复制</button>

在HarmonyOS鸿蒙系统中,针对kvstore保存和获取数据异常的问题,通常可以检查以下几个方面:

  1. 权限配置:确保应用已在config.json中正确配置了读写kvstore的权限。

  2. Key有效性:检查用于保存和获取数据的key是否一致且未超出长度限制。

  3. 数据类型匹配:确保保存和获取数据时使用的数据类型(如int、String等)一致。

  4. 同步与异步:如果使用异步接口,确保在数据实际写入或读取完成后再进行后续操作。

  5. 存储限制:检查是否达到了kvstore的存储上限,必要时进行清理。

  6. 异常处理:在代码中捕获kvstore相关的异常,并查看异常信息以确定具体问题。

  7. 版本兼容性:确保鸿蒙系统版本与kvstore API版本兼容。

如果上述检查后问题依旧存在,可能涉及更底层的系统问题或特定场景的bug。此时,可以通过鸿蒙系统的日志系统收集详细的错误日志,以便进一步分析。同时,也可以尝试重启设备或清除应用数据看是否能恢复。

如果问题依旧没法解决请联系官网客服,官网地址是:https://www.itying.com/category-93-b0.html

回到顶部