HarmonyOS 新手入门:ArkData 用户首选项,无需动辄使用数据库
做 HarmonyOS 数据持久化时,新手很容易先想到数据库。
但不是所有数据都值得建表。比如:昵称、深色模式、字号、是否第一次打开应用,这些都是“小配置”。这种场景用 ArkData 里的用户首选项 Preferences 就够了。
官方文档可以放在手边:
先说结论
Preferences 可以理解成应用自己的本地 key-value 文件。
适合存这些:
- 用户昵称
- 深色模式开关
- 字号大小
- 排序方式
- 是否展示过引导页
不适合存这些:
- 商品列表
- 聊天记录
- 多表关系数据
- 需要复杂查询的数据
一句话:少量配置用 Preferences,复杂业务数据再考虑数据库。
它怎么用
核心就三步。
第一步,拿到首选项文件:
const store = await preferences.getPreferences(context, {
name: 'user_setting_demo'
});
第二步,写入数据:
await store.put('nickname', 'Harmony 新手');
await store.put('darkMode', true);
第三步,保存到本地文件:
await store.flush();
这里有个小坑:put 只是把数据写到 Preferences 实例里,真正落盘要靠 flush。很多人第一次写 Demo 没保存成功,问题就出在漏了这一步。
读取也很简单:
const nickname = store.getSync('nickname', 'Harmony 新手') as string;
第二个参数是默认值。如果本地还没有这个 key,就返回默认值。
这个 Demo 做什么
我写了一个很小的设置页,功能只有三个:
- 输入昵称
- 打开或关闭深色模式
- 调整字号
点击“保存”后写入 Preferences。下次进入页面时,再把这几个值读出来。
这个 Demo 不追求复杂封装,目的就是让新手先把流程跑通:获取实例、读取、写入、删除、落盘。
关键代码
保存时:
await store.put(KEY_NICKNAME, name);
await store.put(KEY_DARK_MODE, this.darkMode);
await store.put(KEY_FONT_SIZE, this.fontSize);
await store.flush();
读取时:
this.nickname = store.getSync(KEY_NICKNAME, 'Harmony 新手') as string;
this.darkMode = store.getSync(KEY_DARK_MODE, false) as boolean;
this.fontSize = store.getSync(KEY_FONT_SIZE, 18) as number;
删除时:
await store.delete(KEY_NICKNAME);
await store.delete(KEY_DARK_MODE);
await store.delete(KEY_FONT_SIZE);
await store.flush();
你会发现,读写逻辑并不复杂。真正要记住的是:修改完数据后,别忘了 flush()。
评论区聊聊
你们平时会把哪些数据放到 Preferences 里?
是主题模式、用户偏好这类配置,还是也会存一些临时业务状态?如果你踩过 flush()、默认值、类型转换这类坑,也可以在评论区补充一下。后面我写 ArkData 其他能力时,可以顺手把这些真实场景带进去。
完整示例代码
ArkDataPreferencesDemo.ets
import { common } from '@kit.AbilityKit';
import { preferences } from '@kit.ArkData';
import { promptAction, router } from '@kit.ArkUI';
const STORE_NAME: string = 'user_setting_demo';
const KEY_NICKNAME: string = 'nickname';
const KEY_DARK_MODE: string = 'darkMode';
const KEY_FONT_SIZE: string = 'fontSize';
@Entry
@Component
struct ArkDataPreferencesDemo {
@State nickname: string = 'Harmony 新手';
@State darkMode: boolean = false;
@State fontSize: number = 18;
@State tips: string = '启动后自动读取本地首选项';
private store: preferences.Preferences | undefined = undefined;
aboutToAppear(): void {
this.loadSettings();
}
private async getStore(): Promise<preferences.Preferences> {
if (this.store !== undefined) {
return this.store;
}
const context = getContext(this) as common.UIAbilityContext;
this.store = await preferences.getPreferences(context, { name: STORE_NAME });
return this.store;
}
private async loadSettings(): Promise<void> {
try {
const store = await this.getStore();
this.nickname = store.getSync(KEY_NICKNAME, 'Harmony 新手') as string;
this.darkMode = store.getSync(KEY_DARK_MODE, false) as boolean;
this.fontSize = store.getSync(KEY_FONT_SIZE, 18) as number;
this.tips = '读取成功:重启应用后仍会保留';
} catch (err) {
this.tips = '读取失败,请查看日志';
console.error('Preferences load failed');
}
}
private async saveSettings(): Promise<void> {
try {
const store = await this.getStore();
const name = this.nickname.length > 0 ? this.nickname : 'Harmony 新手';
await store.put(KEY_NICKNAME, name);
await store.put(KEY_DARK_MODE, this.darkMode);
await store.put(KEY_FONT_SIZE, this.fontSize);
await store.flush();
this.nickname = name;
this.tips = '保存成功:put 后调用 flush 才会落盘';
promptAction.showToast({ message: '保存成功' });
} catch (err) {
this.tips = '保存失败,请查看日志';
promptAction.showToast({ message: '保存失败' });
console.error('Preferences save failed');
}
}
private async resetSettings(): Promise<void> {
try {
const store = await this.getStore();
await store.delete(KEY_NICKNAME);
await store.delete(KEY_DARK_MODE);
await store.delete(KEY_FONT_SIZE);
await store.flush();
this.nickname = 'Harmony 新手';
this.darkMode = false;
this.fontSize = 18;
this.tips = '已清空本页保存的首选项';
} catch (err) {
this.tips = '清空失败,请查看日志';
console.error('Preferences reset failed');
}
}
build() {
Scroll() {
Column({ space: 18 }) {
Row() {
Text('返回')
.fontSize(14)
.fontColor('#0EA5E9')
.onClick(() => {
router.back();
})
Blank()
}
.width('100%')
Text('ArkData Preferences')
.width('100%')
.fontSize(28)
.fontWeight(700)
.fontColor(this.darkMode ? '#F6F7FB' : '#182431')
Text('适合保存昵称、开关、字号这类轻量配置。')
.width('100%')
.fontSize(14)
.fontColor(this.darkMode ? '#AEB6C8' : '#56616F')
Column({ space: 12 }) {
Text('昵称')
.fontSize(14)
.fontColor(this.darkMode ? '#DCE3F2' : '#334155')
TextInput({ placeholder: '输入昵称', text: this.nickname })
.height(44)
.fontSize(16)
.backgroundColor(this.darkMode ? '#202A3A' : '#F1F5F9')
.fontColor(this.darkMode ? '#F8FAFC' : '#0F172A')
.onChange((value: string) => {
this.nickname = value;
})
}
.width('100%')
Row() {
Column({ space: 4 }) {
Text('深色模式')
.fontSize(16)
.fontColor(this.darkMode ? '#F8FAFC' : '#0F172A')
Text(this.darkMode ? '已开启' : '已关闭')
.fontSize(12)
.fontColor(this.darkMode ? '#AEB6C8' : '#64748B')
}
.alignItems(HorizontalAlign.Start)
.layoutWeight(1)
Toggle({ type: ToggleType.Switch, isOn: this.darkMode })
.onChange((isOn: boolean) => {
this.darkMode = isOn;
})
}
.width('100%')
Column({ space: 10 }) {
Row() {
Text('字号')
.fontSize(16)
.fontColor(this.darkMode ? '#F8FAFC' : '#0F172A')
.layoutWeight(1)
Text(`${this.fontSize}`)
.fontSize(16)
.fontWeight(700)
.fontColor('#0EA5E9')
}
.width('100%')
Slider({ value: this.fontSize, min: 14, max: 28, step: 1 })
.onChange((value: number) => {
this.fontSize = value;
})
}
.width('100%')
Text(`你好,${this.nickname}`)
.width('100%')
.padding(16)
.fontSize(this.fontSize)
.fontColor(this.darkMode ? '#F8FAFC' : '#0F172A')
.backgroundColor(this.darkMode ? '#202A3A' : '#E0F2FE')
.borderRadius(8)
Row({ space: 12 }) {
Button('保存')
.layoutWeight(1)
.height(44)
.fontSize(16)
.backgroundColor('#0EA5E9')
.onClick(() => {
this.saveSettings();
})
Button('清空')
.layoutWeight(1)
.height(44)
.fontSize(16)
.fontColor(this.darkMode ? '#F8FAFC' : '#0F172A')
.backgroundColor(this.darkMode ? '#334155' : '#CBD5E1')
.onClick(() => {
this.resetSettings();
})
}
.width('100%')
Text(this.tips)
.width('100%')
.fontSize(13)
.fontColor(this.darkMode ? '#AEB6C8' : '#64748B')
}
.width('100%')
.padding(24)
}
.width('100%')
.height('100%')
.backgroundColor(this.darkMode ? '#111827' : '#FFFFFF')
}
}
- 点赞
- 收藏
- 关注作者
评论(0)