HarmonyOS5 便捷生活类——preferences实现数据跨进程读取(系列见主页)

加入下方官方班级,得鸿蒙礼盒

一起拿鸿蒙礼盒,戳我戳我!!

本期活动时间:2025年8月1日-12月31日


问题现象

通过PersistentStorage存储应用进程的Token数据,在卡片进程中通过AppStorage获取,却取不到Token数据。

背景知识

  • PersistentStorage是应用程序中的可选单例对象。此对象的作用是持久化存储选定的AppStorage属性,以确保这些属性在应用程序重新启动时的值与应用程序关闭时的值相同。
  • AppStorage是应用全局的UI状态存储,是和应用的进程绑定的。AppStorage支持应用的主线程内多个UIAbility实例间的状态共享。AppStorage是UI相关的数据,需要运行在UI线程,无法将对象共享到其他线程
  • 卡片数据交互应用可以通过formProvider.updateForm函数更新指定的卡片。
  • 用户首选项为应用提供Key-Value键值型的数据处理能力,支持应用持久化轻量级数据,并对其修改和查询。可以通过用户首选项方式存储Token。

解决方案

AppStorage不适合跨进程共享数据。此场景“应用与卡片之间数据传递”可以基于用户首选项来实现跨进程数据共享。

  1. UI进程,Index文件存储首选项值。
     
    import { preferences } from '@kit.ArkData';
    import { BusinessError } from '@kit.BasicServicesKit';
    
    @Entry
    @Component
    struct Index {
    @State message: string = 'Hello World';
    
    aboutToAppear(): void {
    let dataPreferences: preferences.Preferences | null = null;
    // 通过调用preferences.getpreferences()实现 获取一个名为myStore的的首选项对象
    preferences.getPreferences(getContext(this), 'myStore', (err: BusinessError, val: preferences.Preferences) => {
    if (err) {
    console.error('Failed to get preferences. code =' + err.code + ', message =' + err.message);
    return;
    }
    dataPreferences = val;
    // 通过Promise异步处理dataPreferences.put方法存储一个键值对,键为'token',值为'123123'
    let promise = dataPreferences.put('token', '123123');
    promise.then(() => {
    // 数据持久化到存储中
    let promise1 = dataPreferences?.flush();
    promise1?.then(() => {
    console.info('Succeeded in flushing.');
    }).catch((err: BusinessError) => {
    console.error('Failed to flush. code =' + err.code + ', message =' + err.message);
    })
    console.info('Succeeded in putting value of \'token\'.');
    }).catch((err: BusinessError) => {
    console.error('Failed to put value of \'token\'. code =' + err.code + ', message =' + err.message);
    })
    console.info('Succeeded in getting preferences.');
    })
    }
    
    build() {
    RelativeContainer() {
    Text(this.message)
    .id('HelloWorld')
    .fontSize(50)
    .fontWeight(FontWeight.Bold)
    .alignRules({
    center: { anchor: '__container__', align: VerticalAlign.Center },
    middle: { anchor: '__container__', align: HorizontalAlign.Center }
    })
    }
    .height('100%')
    .width('100%')
    }
    }

  2. 卡片获取首选项值。
     

    实现效果:上述代码实现token数据存入myStore文件,文件内容为Token的值。

     
    import { formBindingData, FormExtensionAbility } from '@kit.FormKit';
    import { Want } from '@kit.AbilityKit';
    import { preferences } from '@kit.ArkData';
    import { BusinessError } from '@kit.BasicServicesKit';
    
    export default class EntryFormAbility extends FormExtensionAbility {
    // 服务卡片生命周期的一个方法,当服务卡片被添加到前台时触发
    onAddForm(want: Want) {
    let context = this.context;
    let dataPreferences: preferences.Preferences | null = null;
    // 调用getPreferences方法同步获取首选项对象
    preferences.getPreferences(context, 'myStore', (err: BusinessError, val: preferences.Preferences) => {
    if (err) {
    console.error('Failed to get preferences. code =' + err.code + ', message =' + err.message);
    return;
    }
    // 将获取的首选项对象赋值给dataPreferences变量
    dataPreferences = val;
    // 使用get方法异步获取名为'token'的首选项值,如果找不到该值,则使用'default'作为默认值
    let promise = dataPreferences.get('token', 'default')
    promise.then((data: preferences.ValueType) => {
    console.info('Succeeded in getting value of \'startup\'. Data: ' + data);
    }).catch((err: BusinessError) => {
    console.error('Failed to get value of \'startup\'. code =' + err.code + ', message =' + err.message);
    })
    console.info('Succeeded in getting preferences.');
    })
    // 创建并返回一个表单绑定数据对象,用于将数据绑定到服务卡片的视图层
    return formBindingData.createFormBindingData('');
    }
    }

常见FAQ

Q:首选项是否可以多进程并发使用?

A:首选项无法保证进程并发安全,会有文件损坏和数据丢失的风险,不支持在多进程场景下使用。详情参考官网约束限制

Q:用户首选项是线程安全的吗?

A:首选项线程安全,支持多线程访问,确保数据一致性,但仅限同进程,不支持多进程。

Q:DistributedKVStore (分布式键值数据库)与首选项的区别是什么?

A:若需跨设备数据同步或处理复杂业务逻辑,选择 DistributedKVStore,若仅需单设备轻量级存储(如配置项),优先使用 Preferences。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值