数据持久化之首选项
用户首选项为应用提供Key-Value键值型的数据处理能力,支持应用持久化轻量级数据,并对其修改和查询。当用户希望有一个全局唯一存储的地方,可以采用用户首选项来进行存储。Preferences会将该数据缓存在内存中,当用户读取的时候,能够快速从内存中获取数据,当需要持久化时可以使用flush接口将内存中的数据写入持久化文件中。Preferences会随着存放的数据量越多而导致应用占用的内存越大,因此,Preferences不适合存放过多的数据,也不支持通过配置加密,适用的场景一般为应用保存用户的个性化设置(字体大小,是否开启夜间模式)等。
如图所示,用户程序通过ArkTS接口调用用户首选项读写对应的数据文件。开发者可以将用户首选项持久化文件的内容加载到Preferences实例,每个文件唯一对应到一个Preferences实例,系统会通过静态容器将该实例存储在内存中,直到主动从内存中移除该实例或者删除该文件。
应用首选项的持久化文件保存在应用沙箱内部,可以通过context获取其路径。具体可见获取应用文件路径。
图1 用户首选项运作机制
以下是用户首选项持久化功能的相关接口,更多接口及使用方式请见用户首选项。
接口名称 | 描述 |
---|---|
getPreferencesSync(context: Context, options: Options): Preferences | 获取Preferences实例。该接口存在异步接口。 |
putSync(key: string, value: ValueType): void | 将数据写入Preferences实例,可通过flush将Preferences实例持久化。该接口存在异步接口。 |
hasSync(key: string): boolean | 检查Preferences实例是否包含名为给定Key的存储键值对。给定的Key值不能为空。该接口存在异步接口。 |
getSync(key: string, defValue: ValueType): ValueType | 获取键对应的值,如果值为null或者非默认值类型,返回默认数据defValue。该接口存在异步接口。 |
deleteSync(key: string): void | 从Preferences实例中删除名为给定Key的存储键值对。该接口存在异步接口。 |
flush(callback: AsyncCallback<void>): void | 将当前Preferences实例的数据异步存储到用户首选项持久化文件中。 |
on(type: 'change', callback: Callback<string>): void | 订阅数据变更,订阅的数据发生变更后,在执行flush方法后,触发callback回调。 |
off(type: 'change', callback?: Callback<string>): void | 取消订阅数据变更。 |
deletePreferences(context: Context, options: Options, callback: AsyncCallback<void>): void | 从内存中移除指定的Preferences实例。若Preferences实例有对应的持久化文件,则同时删除其持久化文件。 |
import { preferences } from '@kit.ArkData'
@Entry
@Component
struct Index {
build() {
Row() {
Column() {
// 1.0 利用首选项api对store这个文件做一个新增数据:["鸿蒙","HTML5"]
Button('新增/修改数据').onClick(() => {
// 1.0 获取store文件的操作对象
const pre = preferences.getPreferencesSync(getContext(), { name: 'store' })
// 2.0 调用操作对象上的putSync方法完成数据的新增 (这是将数据保存到内存中)
pre.putSync('keyword', ["鸿蒙Next", "huawei"])
pre.putSync('keyword2', ["HTML5", "JavaScript"])
pre.flush() //将内存数据写入到磁盘
AlertDialog.show({ message: '首选项数据写入成功' })
})
}
.width('100%')
}
}
}
结果查询:
修改数据就还是用key值把之前数据修改成需要的就行
代码:
Button('获取数据').onClick(() => {
const pre = preferences.getPreferencesSync(getContext(), { name: 'store' })
AlertDialog.show({ message: JSON.stringify(pre.getAllSync()) })
})
Button('删除数据').onClick(() => {
const pre = preferences.getPreferencesSync(getContext(), { name: 'store' })
pre.deleteSync('keyword')
pre.flush()
AlertDialog.show({ message: '首选项数据删除成功' })
})
通过一个搜索框实例进行系统组合起来
静态结构
@Entry
@Component
struct SearchPage {
@State keyword: string = ''
@State isdel: boolean = false
aboutToAppear(): void {
}
@Builder
itemBuilder(text: string) {
Row({ space: 20 }) {
Text(text)
if (this.isdel) {
Text('x')
.height(30)
.onClick(() => {
AlertDialog.show({ message: '删除' + text })
})
}
}
.margin({ right: 10, top: 10 })
.padding({
left: 15,
right: 15,
top: 5,
bottom: 5
})
.backgroundColor('rgba(0,0,0,0.05)')
.borderRadius(20)
}
build() {
Navigation() {
Column({ space: 15 }) {
// 1. 搜索关键字
TextInput({ placeholder: '输入回车保存数据', text: $$this.keyword })
.onSubmit(() => {
AlertDialog.show({ message: this.keyword })
})
// 2. 关键字列表
Row() {
Text('搜索记录').fontSize(20).fontWeight(800)
Row() {
if (this.isdel) {
Text('全部删除')
.onClick(()=>{
AlertDialog.show({ message: '补上全部删除逻辑' })
})
Text(' | ')
Text('取消删除')
.onClick(()=>{
this.isdel = false
})
} else {
Text('X')
.height(28)
.onClick(()=>{
this.isdel = true
})
}
}
}
.width('100%')
.justifyContent(FlexAlign.SpaceBetween)
// 3. 关键字列表
Flex({ wrap: FlexWrap.Wrap }) {
ForEach([1, 2, 3, 4], (item: number) => {
this.itemBuilder('文本' + item)
})
}
}
.padding(15)
}
.padding({ top: 20 })
.titleMode(NavigationTitleMode.Mini)
.title('搜索页面')
}
}
import { preferences } from '@kit.ArkData'
@Entry
@Component
struct SearchPage {
@State keyword: string = ''
@State isdel: boolean = false
@State keywords: string[] = []
aboutToAppear(): void {
this.getData()
}
// 1.0 新增方法
async saveData(text: string) {
// 非空验证
if(!text){
return
}
// 1.0 获取首选项对象实例
const pre = preferences.getPreferencesSync(getContext(), { name: 'store1' })
// 2.0 调用putsync方法保存数组
// 2.0.1 先从首选项中获取老数据
let dataArr = pre.getSync('keyword', []) as string[]
// 判断如果首选项中已经有了该关键词,不再保存
if(dataArr.includes(text)){
// 该关键字已经存在了,不保存
return
}
dataArr.push(text)
// 2.0.2 存数据
pre.putSync('keyword', dataArr)
// 3.0 调用flush写入到磁盘
await pre.flush()
}
// 2.0 获取首选项数据
async getData() {
const pre = preferences.getPreferencesSync(getContext(), { name: 'store1' })
this.keywords = pre.getSync('keyword', []) as string[]
}
@Builder
itemBuilder(text: string) {
Row({ space: 20 }) {
Text(text)
if (this.isdel) {
Text('x')
.height(30)
.onClick(() => {
AlertDialog.show({ message: '删除' + text })
})
}
}
.margin({ right: 10, top: 10 })
.padding({
left: 15,
right: 15,
top: 5,
bottom: 5
})
.backgroundColor('rgba(0,0,0,0.05)')
.borderRadius(20)
}
build() {
Navigation() {
Column({ space: 15 }) {
// 1. 搜索关键字
TextInput({ placeholder: '输入回车保存数据', text: $$this.keyword })
.onSubmit(async () => {
AlertDialog.show({ message: this.keyword })
// 将关键词数据保存到首选项中
await this.saveData(this.keyword)
await this.getData()
})
// 2. 关键字列表
Row() {
Text('搜索记录').fontSize(20).fontWeight(800)
Row() {
if (this.isdel) {
Text('全部删除')
.onClick(()=>{
AlertDialog.show({ message: '补上全部删除逻辑' })
})
Text(' | ')
Text('取消删除')
.onClick(()=>{
this.isdel = false
})
} else {
Text('X')
.height(28)
.onClick(()=>{
this.isdel = true
})
}
}
}
.width('100%')
.justifyContent(FlexAlign.SpaceBetween)
// 3. 关键字列表
Flex({ wrap: FlexWrap.Wrap }) {
ForEach(this.keywords, (item: string) => {
this.itemBuilder(item)
})
}
}
.padding(15)
}
.padding({ top: 20 })
.titleMode(NavigationTitleMode.Mini)
.title('搜索页面')
}
}
// 3.0 删除指定关键字和全部关键字
async delData(text?: string) {
const pre = preferences.getPreferencesSync(getContext(), { name: 'store1' })
// 1.0 删除全部关键
if (!text) {
pre.deleteSync('keyword')
} else {
// 2.0 删除指定关键字 获取 -> 删除内存数组的关键字 -> 写回
let datas = pre.getSync('keyword', []) as string[]
let cindex = datas.findIndex(item => item === text)
// 当关键字索引为-1的时候,表示没有找到
if (cindex < 0) {
return
}
// 如果有删除
datas.splice(cindex, 1) // 返回值表示删除的元素
// 保存回去
pre.putSync('keyword', datas)
}
// 写回磁盘
pre.flush()
}
// 删除指定关键字
await this.delData(text)
await this.getData()
})
// 删除全局数据
await this.delData()
await this.getData()
})
完整代码
import { preferences } from '@kit.ArkData'
@Entry
@Component
struct SearchPage {
@State keyword: string = ''
@State isdel: boolean = false
@State keywords: string[] = []
aboutToAppear(): void {
this.getData()
}
// 1.0 新增方法
async saveData(text: string) {
// 非空验证
if(!text){
return
}
// 1.0 获取首选项对象实例
const pre = preferences.getPreferencesSync(getContext(), { name: 'store1' })
// 2.0 调用putsync方法保存数组
// 2.0.1 先从首选项中获取老数据
let dataArr = pre.getSync('keyword', []) as string[]
// 判断如果首选项中已经有了该关键词,不再保存
if(dataArr.includes(text)){
// 该关键字已经存在了,不保存
return
}
dataArr.push(text)
// 2.0.2 存数据
pre.putSync('keyword', dataArr)
// 3.0 调用flush写入到磁盘
await pre.flush()
}
// 2.0 获取首选项数据
async getData() {
const pre = preferences.getPreferencesSync(getContext(), { name: 'store1' })
this.keywords = pre.getSync('keyword', []) as string[]
}
// 3.0 删除指定关键字和全部关键字
async delData(text?: string) {
const pre = preferences.getPreferencesSync(getContext(), { name: 'store1' })
// 1.0 删除全部关键
if (!text) {
pre.deleteSync('keyword')
} else {
// 2.0 删除指定关键字 获取 -> 删除内存数组的关键字 -> 写回
let datas = pre.getSync('keyword', []) as string[]
let cindex = datas.findIndex(item => item === text)
// 当关键字索引为-1的时候,表示没有找到
if (cindex < 0) {
return
}
// 如果有删除
datas.splice(cindex, 1) // 返回值表示删除的元素
// 保存回去
pre.putSync('keyword', datas)
}
// 写回磁盘
pre.flush()
}
@Builder
itemBuilder(text: string) {
Row({ space: 20 }) {
Text(text)
if (this.isdel) {
Text('x')
.height(30)
.onClick(async () => {
// 删除指定关键字
await this.delData(text)
await this.getData()
AlertDialog.show({ message: '删除' + text })
})
}
}
.margin({ right: 10, top: 10 })
.padding({
left: 15,
right: 15,
top: 5,
bottom: 5
})
.backgroundColor('rgba(0,0,0,0.05)')
.borderRadius(20)
}
build() {
Navigation() {
Column({ space: 15 }) {
// 1. 搜索关键字
TextInput({ placeholder: '输入回车保存数据', text: $$this.keyword })
.onSubmit(async () => {
AlertDialog.show({ message: this.keyword })
// 将关键词数据保存到首选项中
await this.saveData(this.keyword)
await this.getData()
})
// 2. 关键字列表
Row() {
Text('搜索记录').fontSize(20).fontWeight(800)
Row() {
if (this.isdel) {
Text('全部删除')
.onClick(async ()=>{
// 删除全局数据
await this.delData()
await this.getData()
})
Text(' | ')
Text('取消删除')
.onClick(()=>{
this.isdel = false
})
} else {
Text('X')
.height(28)
.onClick(()=>{
this.isdel = true
})
}
}
}
.width('100%')
.justifyContent(FlexAlign.SpaceBetween)
// 3. 关键字列表
Flex({ wrap: FlexWrap.Wrap }) {
ForEach(this.keywords, (item: string) => {
this.itemBuilder(item)
})
}
}
.padding(15)
}
.padding({ top: 20 })
.titleMode(NavigationTitleMode.Mini)
.title('搜索页面')
}
}
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。