HarmonyOS 鸿蒙Next中preferences为什么获取不到值,得到是undefined

HarmonyOS 鸿蒙Next中preferences为什么获取不到值,得到是undefined

封装的
import { preferences } from "@kit.ArkData"
import { common } from '@kit.AbilityKit'
import { UIAbility } from '@kit.AbilityKit';
import { BusinessError } from "@kit.BasicServicesKit";
import { JSON } from "@kit.ArkTS";
const context = getContext(this) as common.UIAbilityContext
//本地存储
let dataPreference: preferences.Preferences | null = null;
export class StoreUtil {
  // private static dataPreference: preferences.Preferences | null = null;

    public static async init(){
    try{
      // const context = getContext() as common.UIAbilityContext
      dataPreference  =  await  preferences.getPreferences(context, 'userStore');
      console.info('success getPreferences' + JSON.stringify(dataPreference))

    }catch (e) {
      console.log('第一步就报错'+e)
    }
    // dataPreference =  preferences.getPreferences(context, 'userStore');
    // return dataPreference
  }

  public  static async put(key:string,value:string){
    console.log(key,value)
    // 如果不存在则初始化
    if(JSON.stringify(dataPreference)==="{}"){
      console.log('对象内容'+ JSON.stringify(dataPreference) )
      StoreUtil.init()
    }
    //添加数据
    try{
      // dataPreference?.put('startup', 'auto').then(() => {
      //   console.info("Succeeded in putting value of 'startup'.");
      // }).catch((err: BusinessError) => {
      //   console.error("Failed to put value of 'startup'. code =" + err.code + ", message =" + err.message);
      // })
      dataPreference?.putSync(key,value)
      dataPreference?.flushSync()
      console.log('-------------执行----------------')
    }catch (e){
      console.log('添加错误')
    }
  }
  public static async get(key:string){
    console.log(key)
    if(JSON.stringify(dataPreference)==="{}"){
      console.log('未初始化')
      console.log('类型'+ typeof dataPreference)
      StoreUtil.init()
    }
    //获取数据
    dataPreference?.getSync(key,'default')
  }
  public static async delete(key:string){
    if(!dataPreference){
      console.log('未初始化')
      StoreUtil.init()
    }
    //删除数据
    dataPreference?.deleteSync(key)
    dataPreference?.flushSync()
  }
}
//button按钮  存储 用户信息
StoreUtil.put('userdata','1231231')
在首页获取到的值是undefined
let userdata:preferences.ValueType = StoreUtil.get('userdata').then(res=>{
  console.log('-------------首页----------'+res)
})

模拟器版本5.1.1


更多关于HarmonyOS 鸿蒙Next中preferences为什么获取不到值,得到是undefined的实战教程也可以访问 https://www.itying.com/category-93-b0.html

9 回复

你的Preferences是异步初始化的,需等待初始化完成。所有需要 awat StoreUtil.init() ,

get 方法也缺少返回值,需要return

return dataPreference?.getSync(key,'default')

cke_211.png

更多关于HarmonyOS 鸿蒙Next中preferences为什么获取不到值,得到是undefined的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


init()方法没有等待cke_1628.png

  1. 未等待异步初始化完成
    init() 方法是异步操作,但代码中直接调用 StoreUtil.put() 时未确保初始化已完成。建议增加初始化状态判断:

    private static isInitialized = false;
    public static async init() {
      if (this.isInitialized) return;
      try {
        dataPreference = await preferences.getPreferences(context, 'userStore');
        this.isInitialized = true;
      } catch (e) { /* 错误处理 */ }
    }
    

可以存,就是返回值是字符串,而转成对象时,却无法获取到键值对,取到是undefined,

  1. StoreUtil类put方法中初始化Preferences实例判断不正确,dataPreference初始设置为null,使用JSON.stringify(dataPreference) === '{}'固定返回为false,无法进入Preferences实例初始化逻辑。需修改如下:
// 如果不存在则初始化
if (!dataPreference || JSON.stringify(dataPreference) === '{}') {
  StoreUtil.init()
}
  1. StoreUtil类init方法中初始化Preference实例建议使用同步方法,后续的插入、查询、删除都需先确保实例初始化完成。
public static async init() {
  try {
    dataPreference = preferences.getPreferencesSync(context, { name: 'testStore' });
    console.info('success getPreferences' + JSON.stringify(dataPreference))
  } catch (e) {
    console.error('第一步就报错' + e)
  }
}
  1. StoreUtil类get方法从Preference中读取数据后未将数据返回出去,需增加return。
public static async get(key: string) {
  // 如果不存在则初始化
  if (!dataPreference || JSON.stringify(dataPreference) === '{}') {
    StoreUtil.init()
  }
  // 获取数据
  return dataPreference?.getSync(key, 'default')
}

修改后,执行的日志如下:

09-19 12:01:13.792   19412-19412   A03D00/com.hw.example/JSAPP     com.hw.example        I     result is test

问题分析

  1. 初始化未完成:您的代码中StoreUtil.init()是异步操作(使用preferences.getPreferences的Promise版本),但在putget方法中调用init()时没有使用await等待初始化完成。这可能导致在Preferences实例尚未初始化时就执行了存储或获取操作,从而获取到undefined。
  2. get方法未返回值:您的StoreUtil.get()方法内部调用了dataPreference?.getSync(key, 'default'),但没有使用return语句返回结果。这导致方法返回一个解析为undefined的Promise,因此您在首页调用时得到undefined。
  3. 上下文(Context)可能不正确:您使用const context = getContext(this) as common.UIAbilityContext获取context,但在全局或非UIAbility环境中,this可能无法正确指向UIAbilityContext。这会导致Preferences实例创建失败,存储和获取操作无效。
  4. 存储操作可能失败:您的put方法使用了putSyncflushSync,但没有错误处理。如果存储过程中发生错误(如键名无效或存储失败),数据可能未被正确写入,导致获取时返回默认值或undefined。

解决方案

1. 确保初始化完成

  • 修改init方法,确保返回Promise,并在putget中等待初始化完成。
  • 使用单例模式,避免多次初始化。

2. 修正get方法返回值

  • get方法中返回getSync的结果,以便调用方可以获取到值。

3. 确保Context正确

  • 在UIAbility中获取context并全局保存,或在StoreUtil中传递context参数。避免在全局作用域中使用getContext(this),因为this可能未定义。

4. 添加错误处理

  • 在存储和获取操作中添加异常捕获,打印错误日志以便调试。

修改后的代码示例

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

// 全局保存context,需在UIAbility中设置
let globalContext: common.UIAbilityContext | null = null;

// 设置全局context的函数(在UIAbility的onCreate中调用)
export function setGlobalContext(context: common.UIAbilityContext) {
  globalContext = context;
}

let dataPreference: preferences.Preferences | null = null;

export class StoreUtil {
  public static async init(): Promise<void> {
    if (!globalContext) {
      console.error("Context is not set. Please call setGlobalContext first.");
      return;
    }
    try {
      dataPreference = await preferences.getPreferences(globalContext, 'userStore');
      console.info('Succeeded in getting preferences.');
    } catch (e) {
      console.error('Failed to get preferences. Error: ' + e);
    }
  }

  public static async put(key: string, value: preferences.ValueType): Promise<void> {
    if (!dataPreference) {
      await StoreUtil.init();
    }
    if (!dataPreference) {
      console.error("Preferences instance is null.");
      return;
    }
    try {
      dataPreference.putSync(key, value);
      dataPreference.flushSync();
      console.info("Succeeded in putting value.");
    } catch (e) {
      console.error("Failed to put value. Error: " + e);
    }
  }

  public static async get(key: string, defaultValue: preferences.ValueType = 'default'): Promise<preferences.ValueType> {
    if (!dataPreference) {
      await StoreUtil.init();
    }
    if (!dataPreference) {
      console.error("Preferences instance is null.");
      return defaultValue;
    }
    try {
      return dataPreference.getSync(key, defaultValue);
    } catch (e) {
      console.error("Failed to get value. Error: " + e);
      return defaultValue;
    }
  }

  public static async delete(key: string): Promise<void> {
    if (!dataPreference) {
      await StoreUtil.init();
    }
    if (!dataPreference) {
      console.error("Preferences instance is null.");
      return;
    }
    try {
      dataPreference.deleteSync(key);
      dataPreference.flushSync();
      console.info("Succeeded in deleting value.");
    } catch (e) {
      console.error("Failed to delete value. Error: " + e);
    }
  }
}

在UIAbility中设置全局Context

在您的UIAbility(例如EntryAbility)中,设置全局context:

import { UIAbility } from '@kit.AbilityKit';
import { window } from '@kit.ArkUI';
import { setGlobalContext } from '../utils/StoreUtil'; // 调整路径

class EntryAbility extends UIAbility {
  onCreate() {
    setGlobalContext(this.context);
    // 可选:初始化StoreUtil
    StoreUtil.init().then(() => {
      console.info('StoreUtil initialized.');
    });
  }
}

在首页调用

在页面中,确保在操作前等待初始化完成,然后使用async/await或Promise方式调用:

// 存储数据
StoreUtil.put('userdata', '1231231').then(() => {
  console.info('Storage successful.');
});

// 获取数据
StoreUtil.get('userdata').then((res) => {
  console.info('Value from preferences: ' + res);
});

注意事项

  • 同步与异步:您的代码混合了同步和异步方法。如果使用同步方法(如getSync),请确保Preferences实例已初始化。建议统一使用异步方式以避免竞态条件。

分析

  1. 未正确初始化Preferences实例 必须确保preferences.Preferences实例在使用前完成初始化,且每次操作前都通过getPreferences()获取同一实例

  2. 缺少数据持久化操作 存储数据后未调用flush()方法,导致数据未真正写入磁盘

  3. 上下文(Context)不一致 如果通过不同Context(如页面级Context与应用级Context)获取Preferences实例,会因沙箱隔离导致数据无法共享

  4. 生命周期未同步 在组件初始化阶段过早访问Preferences可能导致状态变量未就绪

在HarmonyOS Next中,preferences获取到undefined通常是因为数据未正确存储或读取路径错误。请检查以下方面:

  1. 确保使用preferences.getPreferences()时传入正确的context和name参数。
  2. 存储数据后是否成功调用了flush()flushSync()方法持久化。
  3. 读取时使用的key必须与存储时完全一致,注意大小写。
  4. 确认存储和读取操作在同一个preferences实例中进行。

检查代码逻辑,确保存储流程完整,无异步操作导致的时序问题。

在HarmonyOS Next中,preferences获取不到值(得到undefined)的主要原因是你的StoreUtil.get()方法没有正确返回Promise。从你的代码分析,问题出在以下几个方面:

核心问题分析

  1. get()方法缺少返回值

    public static async get(key:string){
      // ... 代码省略
      dataPreference?.getSync(key,'default')  // 这里执行了但没有返回
    }
    
  2. 调用方式不正确

    // 错误的调用方式
    let userdata = StoreUtil.get('userdata').then(res=>{...})
    

解决方案

1. 修改get()方法,添加返回值:

public static async get(key: string): Promise<preferences.ValueType> {
  console.log(key)
  
  // 检查dataPreference是否初始化
  if (!dataPreference) {
    console.log('未初始化,正在初始化...')
    await StoreUtil.init()
  }
  
  try {
    // 使用getSync同步获取值
    const value = dataPreference?.getSync(key, 'default')
    console.log(`获取到键值 ${key}: ${value}`)
    return Promise.resolve(value)
  } catch (error) {
    console.error(`获取键值 ${key} 失败:`, error)
    return Promise.resolve('default')
  }
}

2. 修改初始化逻辑,确保异步完成:

public static async init(): Promise<void> {
  try {
    if (!dataPreference) {
      dataPreference = await preferences.getPreferences(context, 'userStore')
      console.info('success getPreferences')
    }
  } catch (e) {
    console.error('初始化preferences失败:', e)
  }
}

3. 正确的调用方式:

// 方式1:使用async/await
async function getUserData() {
  try {
    const userdata = await StoreUtil.get('userdata')
    console.log('获取到的用户数据:', userdata)
  } catch (error) {
    console.error('获取数据失败:', error)
  }
}

// 方式2:使用Promise.then
StoreUtil.get('userdata').then(res => {
  console.log('获取到的用户数据:', res)
}).catch(error => {
  console.error('获取数据失败:', error)
})

4. 修复put()方法中的初始化检查:

public static async put(key: string, value: string) {
  // 正确的初始化检查
  if (!dataPreference) {
    console.log('preferences未初始化,正在初始化...')
    await StoreUtil.init()
  }
  
  try {
    dataPreference?.putSync(key, value)
    await dataPreference?.flush()
    console.log(`成功存储键值 ${key}: ${value}`)
  } catch (e) {
    console.error(`存储键值 ${key} 失败:`, e)
  }
}

关键注意事项

  1. 异步初始化:确保在调用get()put()之前,init()方法已经完成执行
  2. 返回值类型get()方法需要明确返回Promise
  3. 错误处理:添加适当的错误处理机制
  4. 同步/异步方法:注意getSync是同步方法,但你的封装需要支持异步调用

按照上述修改后,你的preferences应该能正常获取到存储的值,而不是undefined。

回到顶部