加入下方官方班级,得鸿蒙礼盒
本期活动时间:2025年8月1日-12月31日
问题现象
通过PersistentStorage存储应用进程的Token数据,在卡片进程中通过AppStorage获取,却取不到Token数据。
背景知识
- PersistentStorage是应用程序中的可选单例对象。此对象的作用是持久化存储选定的AppStorage属性,以确保这些属性在应用程序重新启动时的值与应用程序关闭时的值相同。
- AppStorage是应用全局的UI状态存储,是和应用的进程绑定的。AppStorage支持应用的主线程内多个UIAbility实例间的状态共享。AppStorage是UI相关的数据,需要运行在UI线程,无法将对象共享到其他线程。
- 卡片数据交互应用可以通过formProvider.updateForm函数更新指定的卡片。
- 用户首选项为应用提供Key-Value键值型的数据处理能力,支持应用持久化轻量级数据,并对其修改和查询。可以通过用户首选项方式存储Token。
解决方案
AppStorage不适合跨进程共享数据。此场景“应用与卡片之间数据传递”可以基于用户首选项来实现跨进程数据共享。
- 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%') } } - 卡片获取首选项值。
实现效果:上述代码实现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。

被折叠的 条评论
为什么被折叠?



