HarmonyOS鸿蒙Next中如何在非UI组件里面使用preferences存取数据?
HarmonyOS鸿蒙Next中如何在非UI组件里面使用preferences存取数据? 想在非UI组件中使用首选项preferences 保存数据,但是使用preference需要获取context,而在非UI组件中没办法通过getIUContext方法获取context对象。
解决方案
方案一:通过 AppStorage 传递 Context
在应用启动时将 Context 存储到 AppStorage,然后在非 UI 组件中获取。
// 1. 在 EntryAbility 中存储 Context
export default class EntryAbility extends UIAbility {
onCreate(want: Want, launchParam: AbilityConstant.LaunchParam) {
// 存储 applicationContext 到 AppStorage
AppStorage.setOrCreate('applicationContext', this.context.getApplicationContext());
// 或者存储 ability context
AppStorage.setOrCreate('abilityContext', this.context);
}
onWindowStageCreate(windowStage: window.WindowStage) {
windowStage.loadContent('pages/Index', (err) => {
if (err.code) {
return;
}
});
}
}
// 2. 在非 UI 组件中获取 Context 并使用 Preferences
import { preferences } from '@kit.ArkData';
import { common } from '@kit.AbilityKit';
export class PreferencesManager {
private static preferencesInstance: preferences.Preferences | null = null;
private static readonly PREFERENCES_NAME = 'myPreferences';
// 初始化 Preferences
public static async init(): Promise<void> {
try {
// 从 AppStorage 获取 context
let context = AppStorage.get('applicationContext') as common.ApplicationContext;
if (!context) {
console.error('Context not found in AppStorage');
return;
}
// 获取 Preferences 实例
this.preferencesInstance = await preferences.getPreferences(
context,
this.PREFERENCES_NAME
);
console.info('Preferences initialized successfully');
} catch (err) {
console.error(`Failed to init preferences: ${err}`);
}
}
// 保存数据
public static async put(key: string, value: preferences.ValueType): Promise<void> {
if (!this.preferencesInstance) {
await this.init();
}
try {
await this.preferencesInstance?.put(key, value);
await this.preferencesInstance?.flush();
console.info(`Data saved: ${key} = ${value}`);
} catch (err) {
console.error(`Failed to put data: ${err}`);
}
}
// 获取数据
public static async get(key: string, defaultValue: preferences.ValueType): Promise<preferences.ValueType> {
if (!this.preferencesInstance) {
await this.init();
}
try {
let value = await this.preferencesInstance?.get(key, defaultValue);
return value ?? defaultValue;
} catch (err) {
console.error(`Failed to get data: ${err}`);
return defaultValue;
}
}
// 删除数据
public static async delete(key: string): Promise<void> {
if (!this.preferencesInstance) {
await this.init();
}
try {
await this.preferencesInstance?.delete(key);
await this.preferencesInstance?.flush();
console.info(`Data deleted: ${key}`);
} catch (err) {
console.error(`Failed to delete data: ${err}`);
}
}
// 清空所有数据
public static async clear(): Promise<void> {
if (!this.preferencesInstance) {
await this.init();
}
try {
await this.preferencesInstance?.clear();
await this.preferencesInstance?.flush();
console.info('All data cleared');
} catch (err) {
console.error(`Failed to clear data: ${err}`);
}
}
}
方案二:使用单例模式的 Context 管理器
创建一个专门的 Context 管理类:
// ContextManager.ts
import { common } from '@kit.AbilityKit';
export class ContextManager {
private static instance: ContextManager;
private applicationContext: common.ApplicationContext | null = null;
private abilityContext: common.UIAbilityContext | null = null;
private constructor() {}
public static getInstance(): ContextManager {
if (!ContextManager.instance) {
ContextManager.instance = new ContextManager();
}
return ContextManager.instance;
}
// 设置 ApplicationContext
public setApplicationContext(context: common.ApplicationContext): void {
this.applicationContext = context;
}
// 设置 AbilityContext
public setAbilityContext(context: common.UIAbilityContext): void {
this.abilityContext = context;
}
// 获取 ApplicationContext
public getApplicationContext(): common.ApplicationContext | null {
return this.applicationContext;
}
// 获取 AbilityContext
public getAbilityContext(): common.UIAbilityContext | null {
return this.abilityContext;
}
}
// 在 EntryAbility 中初始化
export default class EntryAbility extends UIAbility {
onCreate(want: Want, launchParam: AbilityConstant.LaunchParam) {
ContextManager.getInstance().setApplicationContext(
this.context.getApplicationContext()
);
ContextManager.getInstance().setAbilityContext(this.context);
}
}
// 在非 UI 组件中使用
import { preferences } from '@kit.ArkData';
import { ContextManager } from './ContextManager';
export class DataService {
public static async saveData(key: string, value: string): Promise<void> {
let context = ContextManager.getInstance().getApplicationContext();
if (!context) {
console.error('Context not available');
return;
}
try {
let prefs = await preferences.getPreferences(context, 'myPreferences');
await prefs.put(key, value);
await prefs.flush();
} catch (err) {
console.error(`Failed to save data: ${err}`);
}
}
}
方案三:通过参数传递 Context
如果非 UI 组件是从 UI 组件调用的,可以直接传递 Context:
// 非 UI 组件
export class StorageHelper {
private context: common.Context;
constructor(context: common.Context) {
this.context = context;
}
public async saveUserInfo(username: string, age: number): Promise<void> {
try {
let prefs = await preferences.getPreferences(this.context, 'userPrefs');
await prefs.put('username', username);
await prefs.put('age', age);
await prefs.flush();
} catch (err) {
console.error(`Failed to save user info: ${err}`);
}
}
public async getUserInfo(): Promise<{ username: string; age: number }> {
try {
let prefs = await preferences.getPreferences(this.context, 'userPrefs');
let username = await prefs.get('username', '') as string;
let age = await prefs.get('age', 0) as number;
return { username, age };
} catch (err) {
console.error(`Failed to get user info: ${err}`);
return { username: '', age: 0 };
}
}
}
// 在 UI 组件中使用
@Entry
@Component
struct Index {
private storageHelper: StorageHelper | null = null;
aboutToAppear() {
// 通过 getContext 获取 context 并传递
this.storageHelper = new StorageHelper(getContext(this));
}
build() {
Column() {
Button('保存数据')
.onClick(async () => {
await this.storageHelper?.saveUserInfo('张三', 25);
})
Button('读取数据')
.onClick(async () => {
let userInfo = await this.storageHelper?.getUserInfo();
console.info(`User: ${userInfo?.username}, Age: ${userInfo?.age}`);
})
}
}
}
方案四:使用 GlobalContext(适用于全局单例)
// GlobalContext.ts
export class GlobalContext {
private static instance: GlobalContext;
private objects = new Map<string, Object>();
private constructor() {}
public static getInstance(): GlobalContext {
if (!GlobalContext.instance) {
GlobalContext.instance = new GlobalContext();
}
return GlobalContext.instance;
}
public setObject(key: string, obj: Object): void {
this.objects.set(key, obj);
}
public getObject(key: string): Object | undefined {
return this.objects.get(key);
}
}
// 在 EntryAbility 中设置
export default class EntryAbility extends UIAbility {
onCreate(want: Want, launchParam: AbilityConstant.LaunchParam) {
GlobalContext.getInstance().setObject('context', this.context);
}
}
// 在非 UI 组件中使用
import { preferences } from '@kit.ArkData';
import { common } from '@kit.AbilityKit';
import { GlobalContext } from './GlobalContext';
export class PreferenceUtil {
public static async saveData(key: string, value: preferences.ValueType): Promise<void> {
let context = GlobalContext.getInstance().getObject('context') as common.UIAbilityContext;
if (!context) {
console.error('Context not found');
return;
}
try {
let prefs = await preferences.getPreferences(context, 'myStore');
await prefs.put(key, value);
await prefs.flush();
} catch (err) {
console.error(`Failed to save data: ${err}`);
}
}
}
完整使用示例
// 1. 在应用启动时初始化(EntryAbility.ets)
export default class EntryAbility extends UIAbility {
onCreate(want: Want, launchParam: AbilityConstant.LaunchParam) {
AppStorage.setOrCreate('applicationContext', this.context.getApplicationContext());
}
async onWindowStageCreate(windowStage: window.WindowStage) {
// 初始化 PreferencesManager
await PreferencesManager.init();
windowStage.loadContent('pages/Index', (err) => {
// ...
});
}
}
// 2. 在任意非 UI 组件中使用
export class UserService {
public static async login(username: string, password: string): Promise<boolean> {
// 模拟登录逻辑
if (username && password) {
// 保存登录状态
await PreferencesManager.put('isLoggedIn', true);
await PreferencesManager.put('username', username);
await PreferencesManager.put('loginTime', Date.now());
return true;
}
return false;
}
public static async logout(): Promise<void> {
await PreferencesManager.put('isLoggedIn', false);
await PreferencesManager.delete('username');
}
public static async isLoggedIn(): Promise<boolean> {
let isLoggedIn = await PreferencesManager.get('isLoggedIn', false);
return isLoggedIn as boolean;
}
}
更多关于HarmonyOS鸿蒙Next中如何在非UI组件里面使用preferences存取数据?的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
1、可以先将preference相关接口封装成一个工具类。示例如下:
import { preferences } from "@kit.ArkData";
export class StoreUtil {
private tokenStore?: preferences.Preferences;
private context: Context;
private static STORE_UTIL: StoreUtil;
constructor(context: Context) {
this.context = context;
}
public static getInstance(context: Context): StoreUtil {
if (!StoreUtil.STORE_UTIL ) {
StoreUtil.STORE_UTIL = new StoreUtil(context);
}
return StoreUtil.STORE_UTIL;
}
public async initStore(): Promise<void> {
try {
this.tokenStore = await preferences.getPreferences(this.context, 'TokenStore');
} catch (e) {
console.error(`initStore fail:${JSON.stringify(e)}`);
}
}
public async putData(key: string, value: string): Promise<void> {
try {
if (!this.tokenStore) {
await this.initStore();
}
this.tokenStore?.put(key,value);
} catch (e) {
console.error(`putData fail:${JSON.stringify(e)}`);
}
}
public async getData(key: string): Promise<string> {
let result: string = '';
try {
if (!this.tokenStore) {
await this.initStore();
}
result = await this.tokenStore?.get(key, 'defaultData') as string;
} catch (e) {
console.error(`getData fail:${JSON.stringify(e)}`);
}
return result;
}
}
2、创建工具类实例
2.1 在UIAbility的onCreate或者onWindowStageCreate中将context传入工具类中。示例如下:
export default class EntryAbility extends UIAbility {
....
onWindowStageCreate(windowStage: window.WindowStage): void {
// Main window is created, set main page for this ability
hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onWindowStageCreate');
StoreUtil.getInstance(this.context);//创建StoreUtil实例,后面使用preference进行数据
存取时,直接调用工具类接口
windowStage.loadContent('pages/Index', (err) => {
if (err.code) {
hilog.error(DOMAIN, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err));
return;
}
hilog.info(DOMAIN, 'testTag', 'Succeeded in loading the content.');
});
}
.....
}
2.2 或者在UI组件中,通过组件内置方法getUIContext,获取context,实例化工具类。示例如下:
import common from '@ohos.app.ability.common';
import { StoreUtil } from '../common/StoreUtil';
@Entry
@Component
struct Index {
private storeUtil: StoreUtil = StoreUtil.getInstance(this.getUIContext().getHostContext() as common.UIAbilityContext);
aboutToAppear(): void {
this.storeUtil.initStore();
}
build() {
Column({ space: 20 }) {
Button('PutData')
.fontSize($r('app.float.page_text_font_size'))
.fontWeight(FontWeight.Bold)
.onClick((e: ClickEvent) => {
this.storeUtil.putData('test', 'TestData001');
})
Button('getData')
.id('HelloWorld')
.fontSize($r('app.float.page_text_font_size'))
.fontWeight(FontWeight.Bold)
.onClick(async (e: ClickEvent) => {
let result: string = await this.storeUtil.getData('test');
console.info(`=-=: result from preference:${result}`);
})
}
.height('100%')
.width('100%')
}
}
3、在使用preference进行数据存取的地方,可以直接使用该工具类进行操作。
在HarmonyOS Next中,非UI组件使用Preferences存取数据需导入@kit.ArkData模块。通过preferences.getPreferences获取Preferences实例,支持异步或同步方式。使用put方法存储数据,如preferences.put('key', value),再调用flush提交。读取时用get方法,如preferences.get('key', defaultValue)。操作完成后调用close释放资源。确保在EntryAbility或UI上下文外直接调用Preferences API,无需依赖UI组件。
在HarmonyOS Next中,非UI组件(如Service或工具类)可通过全局上下文获取UIContext。使用getContext()方法获取全局Context后,调用getUIAbilityContext()转为UIAbilityContext,即可创建Preferences实例:
import preferences from '@ohos.data.preferences';
// 获取全局上下文并转换为UIAbilityContext
const context = getContext() as common.UIAbilityContext;
const uiAbilityContext = context.getUIAbilityContext();
// 创建Preferences实例
const preferencesName = 'myPrefs';
preferences.getPreferences(uiAbilityContext, preferencesName)
.then((pref) => {
// 存取数据
pref.put('key', 'value').flush();
});
注意:
- 确保在UIAbility或ExtensionAbility上下文中调用
- 数据操作需在UI线程执行,非UI线程需通过TaskPool处理
- 存取完成后及时调用flush()持久化数据
此方式适用于Service、工具类等非UI组件的数据持久化需求。

