Next版本——鸿蒙数据长期化之首选项

打印 上一主题 下一主题

主题 1763|帖子 1763|积分 5289

场景介绍

用户首选项为应用提供Key-Value键值型的数据处理能力,支持应用长期化轻量级数据,并对其修改和查询。当用户希望有一个全局唯一存储的地方,可以采用用户首选项来举行存储。Preferences会将该数据缓存在内存中,当用户读取的时候,能够快速从内存中获取数据,当必要长期化时可以使用flush接口将内存中的数据写入长期化文件中。Preferences会随着存放的数据量越多而导致应用占用的内存越大,因此,Preferences不适合存放过多的数据,也不支持通过配置加密,适用的场景一样平常为应用保存用户的个性化设置(字体大小,是否开启夜间模式)等。
运作机制

如图所示,用户程序通过ArkTS接口调用用户首选项读写对应的数据文件。开发者可以将用户首选项长期化文件的内容加载到Preferences实例,每个文件唯一对应到一个Preferences实例,系统会通过静态容器将该实例存储在内存中,直到自动从内存中移除该实例大概删除该文件。
应用首选项的长期化文件保存在应用沙箱内部,可以通过context获取其路径。具体可见获取应用文件路径。
图1 用户首选项运作机制


束缚限定



  • 首选项无法保证进程并发安全,会有文件损坏和数据丢失的风险,不支持在多进程场景下使用。
  • Key键为string类型,要求非空且长度不超过1024个字节。
  • 如果Value值为string类型,请使用UTF-8编码格式,可以为空,不为空时长度不超过16 * 1024 * 1024个字节。
  • 内存会随着存储数据量的增大而增大,以是存储的数据量应该是轻量级的,发起存储的数据不超过一万条,否则会在内存方面产生较大的开销。
接口说明

以下是用户首选项长期化功能的相干接口,更多接口及使用方式请见用户首选项。
接口名称描述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实例有对应的长期化文件,则同时删除其长期化文件。 开发步调

新增/修改数据



复制代码
  1. import { preferences } from '@kit.ArkData'
  2. @Entry
  3. @Component
  4. struct Index {
  5.   build() {
  6.    Row() {
  7.      Column() {
  8.        // 1.0 利用首选项api对store这个文件做一个新增数据:["鸿蒙","HTML5"]
  9.        Button('新增/修改数据').onClick(() => {
  10.          //   1.0 获取store文件的操作对象
  11.          const pre = preferences.getPreferencesSync(getContext(), { name: 'store' })
  12.          //   2.0 调用操作对象上的putSync方法完成数据的新增 (这是将数据保存到内存中)
  13.          pre.putSync('keyword', ["鸿蒙Next", "huawei"])
  14.          pre.putSync('keyword2', ["HTML5", "JavaScript"])
  15.          pre.flush() //将内存数据写入到磁盘
  16.          AlertDialog.show({ message: '首选项数据写入成功' })
  17.        })
  18.      }
  19.      .width('100%')
  20.    }
  21.   }
  22. }
复制代码


结果查询:

修改数据就还是用key值把之前数据修改成必要的就行
查询数据



代码:

  1. Button('获取数据').onClick(() => {
  2.  const pre = preferences.getPreferencesSync(getContext(), { name: 'store' })
  3.  AlertDialog.show({ message: JSON.stringify(pre.getAllSync()) })
  4. })
复制代码

删除数据



  1. Button('删除数据').onClick(() => {
  2.          const pre = preferences.getPreferencesSync(getContext(), { name: 'store' })
  3.          pre.deleteSync('keyword')
  4.          pre.flush()
  5.          AlertDialog.show({ message: '首选项数据删除成功' })
  6.        })
复制代码


实例

通过一个搜刮框实例举行系统组合起来
静态结构
  1. @Entry
  2. @Component
  3. struct SearchPage {
  4.   @State keyword: string = ''
  5.   @State isdel: boolean = false
  6.   aboutToAppear(): void {
  7.   }
  8.   @Builder
  9.   itemBuilder(text: string) {
  10.    Row({ space: 20 }) {
  11.      Text(text)
  12.      if (this.isdel) {
  13.        Text('x')
  14.          .height(30)
  15.          .onClick(() => {
  16.            AlertDialog.show({ message: '删除' + text })
  17.          })
  18.      }
  19.    }
  20.    .margin({ right: 10, top: 10 })
  21.    .padding({
  22.      left: 15,
  23.      right: 15,
  24.      top: 5,
  25.      bottom: 5
  26.    })
  27.    .backgroundColor('rgba(0,0,0,0.05)')
  28.    .borderRadius(20)
  29.   }
  30.   build() {
  31.    Navigation() {
  32.      Column({ space: 15 }) {
  33.        // 1. 搜索关键字
  34.        TextInput({ placeholder: '输入回车保存数据', text: $$this.keyword })
  35.          .onSubmit(() => {
  36.            AlertDialog.show({ message: this.keyword })
  37.          })
  38.        // 2. 关键字列表
  39.        Row() {
  40.          Text('搜索记录').fontSize(20).fontWeight(800)
  41.          Row() {
  42.            if (this.isdel) {
  43.              Text('全部删除')
  44.                .onClick(()=>{
  45.                  AlertDialog.show({ message: '补上全部删除逻辑' })
  46.                })
  47.              Text(' | ')
  48.              Text('取消删除')
  49.                .onClick(()=>{
  50.                  this.isdel = false
  51.                })
  52.            } else {
  53.              Text('X')
  54.                .height(28)
  55.                .onClick(()=>{
  56.                  this.isdel = true
  57.                })
  58.            }
  59.          }
  60.        }
  61.        .width('100%')
  62.        .justifyContent(FlexAlign.SpaceBetween)
  63.        //   3. 关键字列表
  64.        Flex({ wrap: FlexWrap.Wrap }) {
  65.          ForEach([1, 2, 3, 4], (item: number) => {
  66.            this.itemBuilder('文本' + item)
  67.          })
  68.        }
  69.      }
  70.      .padding(15)
  71.    }
  72.    .padding({ top: 20 })
  73.    .titleMode(NavigationTitleMode.Mini)
  74.    .title('搜索页面')
  75.   }
  76. }<img alt=""  src="https://i-blog.csdnimg.cn/direct/c701d153f1a74d8dba60902e304c9fce.png"  />
复制代码
实现历史搜刮记录

保存关键字数组

  1. import { preferences } from '@kit.ArkData'
  2. @Entry
  3. @Component
  4. struct SearchPage {
  5.  @State keyword: string = ''
  6.  @State isdel: boolean = false
  7.  @State keywords: string[] = []
  8.  aboutToAppear(): void {
  9.    this.getData()
  10.   }
  11.  // 1.0 新增方法
  12.  async saveData(text: string) {
  13.    // 非空验证
  14.    if(!text){
  15.      return
  16.    }
  17.    // 1.0 获取首选项对象实例
  18.    const pre = preferences.getPreferencesSync(getContext(), { name: 'store1' })
  19.    // 2.0 调用putsync方法保存数组
  20.    // 2.0.1 先从首选项中获取老数据
  21.    let dataArr = pre.getSync('keyword', []) as string[]
  22.    // 判断如果首选项中已经有了该关键词,不再保存
  23.    if(dataArr.includes(text)){
  24.      // 该关键字已经存在了,不保存
  25.      return
  26.    }
  27.    dataArr.push(text)
  28.    // 2.0.2 存数据
  29.    pre.putSync('keyword', dataArr)
  30.    // 3.0 调用flush写入到磁盘
  31.    await pre.flush()
  32.   }
  33.  // 2.0 获取首选项数据
  34.  async getData() {
  35.    const pre = preferences.getPreferencesSync(getContext(), { name: 'store1' })
  36.    this.keywords = pre.getSync('keyword', []) as string[]
  37.   }
  38.  @Builder
  39.  itemBuilder(text: string) {
  40.    Row({ space: 20 }) {
  41.      Text(text)
  42.      if (this.isdel) {
  43.        Text('x')
  44.          .height(30)
  45.          .onClick(() => {
  46.            AlertDialog.show({ message: '删除' + text })
  47.          })
  48.      }
  49.    }
  50.    .margin({ right: 10, top: 10 })
  51.    .padding({
  52.      left: 15,
  53.      right: 15,
  54.      top: 5,
  55.      bottom: 5
  56.    })
  57.    .backgroundColor('rgba(0,0,0,0.05)')
  58.    .borderRadius(20)
  59.   }
  60.  build() {
  61.    Navigation() {
  62.      Column({ space: 15 }) {
  63.        // 1. 搜索关键字
  64.        TextInput({ placeholder: '输入回车保存数据', text: $$this.keyword })
  65.          .onSubmit(async () => {
  66.            AlertDialog.show({ message: this.keyword })
  67.            //   将关键词数据保存到首选项中
  68.            await  this.saveData(this.keyword)
  69.            await this.getData()
  70.          })
  71.        // 2. 关键字列表
  72.        Row() {
  73.          Text('搜索记录').fontSize(20).fontWeight(800)
  74.          Row() {
  75.            if (this.isdel) {
  76.              Text('全部删除')
  77.                .onClick(()=>{
  78.                  AlertDialog.show({ message: '补上全部删除逻辑' })
  79.                })
  80.              Text(' | ')
  81.              Text('取消删除')
  82.                .onClick(()=>{
  83.                  this.isdel = false
  84.                })
  85.            } else {
  86.              Text('X')
  87.                .height(28)
  88.                .onClick(()=>{
  89.                  this.isdel = true
  90.                })
  91.            }
  92.          }
  93.        }
  94.        .width('100%')
  95.        .justifyContent(FlexAlign.SpaceBetween)
  96.        //   3. 关键字列表
  97.        Flex({ wrap: FlexWrap.Wrap }) {
  98.          ForEach(this.keywords, (item: string) => {
  99.            this.itemBuilder(item)
  100.          })
  101.        }
  102.      }
  103.      .padding(15)
  104.    }
  105.    .padding({ top: 20 })
  106.    .titleMode(NavigationTitleMode.Mini)
  107.    .title('搜索页面')
  108.   }
  109. }
复制代码

删除指定关键字/全部关键字

  1.   async delData(text?: string) {
  2.    const pre = preferences.getPreferencesSync(getContext(), { name: 'store1' })
  3.    //   1.0 删除全部关键
  4.    if (!text) {
  5.      pre.deleteSync('keyword')
  6.    } else {
  7.      // 2.0 删除指定关键字  获取 -> 删除内存数组的关键字 -> 写回
  8.      let datas = pre.getSync('keyword', []) as string[]
  9.      let cindex = datas.findIndex(item => item === text)
  10.      // 当关键字索引为-1的时候,表示没有找到
  11.      if (cindex < 0) {
  12.        return
  13.      }
  14.      // 如果有删除
  15.      datas.splice(cindex, 1) // 返回值表示删除的元素
  16.      //   保存回去
  17.      pre.putSync('keyword', datas)
  18.    }
  19.    // 写回磁盘
  20.    pre.flush()
  21.   }
复制代码
  1.          //  删除指定关键字
  2.          await this.delData(text)
  3.          await this.getData()
  4.        })
复制代码
  1.               // 删除全局数据
  2.               await this.delData()
  3.               await this.getData()
  4.             })
复制代码

完整代码
  1. import { preferences } from '@kit.ArkData'
  2. @Entry
  3. @Component
  4. struct SearchPage {
  5.   @State keyword: string = ''
  6.   @State isdel: boolean = false
  7.   @State keywords: string[] = []
  8.   aboutToAppear(): void {
  9.     this.getData()
  10.   }
  11.   // 1.0 新增方法
  12.   async saveData(text: string) {
  13.     // 非空验证
  14.     if(!text){
  15.       return
  16.     }
  17.     // 1.0 获取首选项对象实例
  18.     const pre = preferences.getPreferencesSync(getContext(), { name: 'store1' })
  19.     // 2.0 调用putsync方法保存数组
  20.     // 2.0.1 先从首选项中获取老数据
  21.     let dataArr = pre.getSync('keyword', []) as string[]
  22.     // 判断如果首选项中已经有了该关键词,不再保存
  23.     if(dataArr.includes(text)){
  24.       // 该关键字已经存在了,不保存
  25.       return
  26.     }
  27.     dataArr.push(text)
  28.     // 2.0.2 存数据
  29.     pre.putSync('keyword', dataArr)
  30.     // 3.0 调用flush写入到磁盘
  31.     await pre.flush()
  32.   }
  33.   // 2.0 获取首选项数据
  34.   async getData() {
  35.     const pre = preferences.getPreferencesSync(getContext(), { name: 'store1' })
  36.     this.keywords = pre.getSync('keyword', []) as string[]
  37.   }
  38.   // 3.0 删除指定关键字和全部关键字
  39.   async delData(text?: string) {
  40.     const pre = preferences.getPreferencesSync(getContext(), { name: 'store1' })
  41.     //   1.0 删除全部关键
  42.     if (!text) {
  43.       pre.deleteSync('keyword')
  44.     } else {
  45.       // 2.0 删除指定关键字  获取 -> 删除内存数组的关键字 -> 写回
  46.       let datas = pre.getSync('keyword', []) as string[]
  47.       let cindex = datas.findIndex(item => item === text)
  48.       // 当关键字索引为-1的时候,表示没有找到
  49.       if (cindex < 0) {
  50.         return
  51.       }
  52.       // 如果有删除
  53.       datas.splice(cindex, 1) // 返回值表示删除的元素
  54.       //   保存回去
  55.       pre.putSync('keyword', datas)
  56.     }
  57.     // 写回磁盘
  58.     pre.flush()
  59.   }
  60.   @Builder
  61.   itemBuilder(text: string) {
  62.     Row({ space: 20 }) {
  63.       Text(text)
  64.       if (this.isdel) {
  65.         Text('x')
  66.           .height(30)
  67.           .onClick(async () => {
  68.             //  删除指定关键字
  69.             await this.delData(text)
  70.             await this.getData()
  71.             AlertDialog.show({ message: '删除' + text })
  72.           })
  73.       }
  74.     }
  75.     .margin({ right: 10, top: 10 })
  76.     .padding({
  77.       left: 15,
  78.       right: 15,
  79.       top: 5,
  80.       bottom: 5
  81.     })
  82.     .backgroundColor('rgba(0,0,0,0.05)')
  83.     .borderRadius(20)
  84.   }
  85.   build() {
  86.     Navigation() {
  87.       Column({ space: 15 }) {
  88.         // 1. 搜索关键字
  89.         TextInput({ placeholder: '输入回车保存数据', text: $$this.keyword })
  90.           .onSubmit(async () => {
  91.             AlertDialog.show({ message: this.keyword })
  92.             //   将关键词数据保存到首选项中
  93.             await  this.saveData(this.keyword)
  94.             await this.getData()
  95.           })
  96.         // 2. 关键字列表
  97.         Row() {
  98.           Text('搜索记录').fontSize(20).fontWeight(800)
  99.           Row() {
  100.             if (this.isdel) {
  101.               Text('全部删除')
  102.                 .onClick(async ()=>{
  103.                   // 删除全局数据
  104.                   await this.delData()
  105.                   await this.getData()
  106.                 })
  107.               Text(' | ')
  108.               Text('取消删除')
  109.                 .onClick(()=>{
  110.                   this.isdel = false
  111.                 })
  112.             } else {
  113.               Text('X')
  114.                 .height(28)
  115.                 .onClick(()=>{
  116.                   this.isdel = true
  117.                 })
  118.             }
  119.           }
  120.         }
  121.         .width('100%')
  122.         .justifyContent(FlexAlign.SpaceBetween)
  123.         //   3. 关键字列表
  124.         Flex({ wrap: FlexWrap.Wrap }) {
  125.           ForEach(this.keywords, (item: string) => {
  126.             this.itemBuilder(item)
  127.           })
  128.         }
  129.       }
  130.       .padding(15)
  131.     }
  132.     .padding({ top: 20 })
  133.     .titleMode(NavigationTitleMode.Mini)
  134.     .title('搜索页面')
  135.   }
  136. }
复制代码
总结



  • 该文档介绍了用户首选项数据长期化的概念、束缚和接口,并通过一个搜刮页面的实例展示了怎样使用用户首选项存储、查询、修改和删除数据。
  • 开发者在使用时需注意数据量的控制和进程安全问题,公道利用接口实现数据的长期化操作,确保应用的正常运行和数据的一致性。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

熊熊出没

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表