【中工开发者】HarmonyOS数据存储--首选项存储、关系型数据存储 ...

打印 上一主题 下一主题

主题 1035|帖子 1035|积分 3105

目次:

               首选项存储

               关系型数据存储



         数据存储是为了办理应用数据长期化题目,使得数据可以大概存储在外存中,到达保存或共享目标。
         鸿蒙数据存储方式支持本地数据存储和分布式存储。
  本地存储是把应用的数据存在本地,即应用所必要的数据存储在应用自己所在的设备上。
        分布式存储是把应用的数据分布在多个设备上,应用可以在多个设备之间进行数据的共享和同步等。
         本文章只讲解鸿蒙数据存储中的首选项存储、关系型数据存储两种数据存储。
   一、首选项存储

概念及访问机制

   首选项存储(Preferences):提供了轻量级配置数据的长期化本领,并支持订阅数据变化的关照本领。仅支持本地存储,常用于保存应用配置信息、用户偏好设置等。
         首选项数据存储也称为偏好数据存储或轻量级数据存储,得当于少量的数据存储,如:登录账户暗码、配置信息等。 首选项数据存储具有访问速率快,存取效率高的特点。 首选项数据存储数据最终是存储在操纵体系的文件中的,体系提供对底层文件读写的封装,并把底层文件映射成Preferences实例对象。
       存储访问机制,每一个底层文件对应一个Preferences实例,应用可以借助Preferences提供的接口方法,进行读写数据。 首选项数据库存储的访问机制如图所示:


代码示例

下面部分代码示例展示了一个简单的首选项存储机制,允许用户自定义界面元素的样式,并将这些设置保存到本地存储中。
注明:DevEcoStudio版本

这段代码是一个HarmonyOS应用中的首选项存储工具类PrefUtil,它利用@kit.ArkData模块中的preferences API来保存和读取应用的字体巨细和颜色设置

其存储数据可以在Device File Browser - data - preferences中检察

导入相应包
  1. import { defaultColor } from  '../pages/Index';
  2. import { defaultSize } from '../pages/Index';
  3. import { preferences as Pref } from '@kit.ArkData';
复制代码
PreUtil.ets页面代码,该部分代码主要负责数据同步存储到本地。
  1. const DB_NAME = 'myBb'; //存储名
  2. const KEY_SIZE = 'keySize'; //键,存字体大小
  3. const KEY_COLOR = 'keyColor'; //键,村字体颜色
  4. class PrefUtil {
  5.     // 获得Preferecnes实例,这是与本地存储交互的接口
  6.     getFontPreferences(): Pref.Preferences {
  7.             let options: Pref.Options =  { name: DB_NAME };
  8.             //使用Pref.getPreferencesSync方法同步获取偏好设置
  9.             let  pref:Pref.Preferences = Pref.getPreferencesSync( getContext(), options);
  10.             return pref;
  11.      }
  12.     // 保存样式,包括大小和颜色
  13.     saveFontStyle(fontSize: number, fontColor: string) {
  14.         const preferences: Pref.Preferences = this.getFontPreferences();
  15.         // 使用putSync方法同步写入数据,并调用flush方法确保数据被保存
  16.         preferences.putSync(KEY_SIZE, fontSize);
  17.         preferences.putSync(KEY_COLOR, fontColor);
  18.         preferences.flush();
  19.     }
  20.     // 异步获得字体大小
  21.     async getFontSize() {
  22.         //如果本地存储中没有值,则返回默认值defaultSize
  23.         let fontSize: number = defaultSize;
  24.         const preferences:Pref.Preferences =  this.getFontPreferences();
  25.         fontSize = preferences.getSync(KEY_SIZE, fontSize) as number;
  26.         return fontSize;
  27.     }
  28.     // 异步获得字体颜色
  29.     async getFontColor() {
  30.         let fontColor: string = defaultColor;
  31.         const preferences:Pref.Preferences =  this.getFontPreferences();
  32.         // 从数据库中获得颜色,如果无则使用默认值
  33.         fontColor =  preferences.getSync(KEY_COLOR, fontColor) as string;
  34.         return fontColor;
  35.     }
  36. }
  37. export default new PrefUtil(); //导出对象
复制代码
Index.ets页面代码,计划页面结构。
  1. import PrefUtil from '../common/PrefUtil'
  2. // 默认大小和颜色
  3. export const defaultSize: number = 50
  4. export const defaultColor: string = '0xFF0000'
  5. @Entry
  6. @Component
  7. struct Index {
  8.   @State message: string = '首选项存储'
  9.   @State saveSize: number = defaultSize
  10.   @State saveColor: string = defaultColor
  11.   @State isSave: boolean = false
  12.   onPageShow() {
  13.     // 显示时加载已保存的值
  14.     PrefUtil.getFontSize().then((value) => {
  15.       this.saveSize = value
  16.     })
  17.     PrefUtil.getFontColor().then((value) => {
  18.       this.saveColor = value
  19.     })
  20.   }
  21.   build() {
  22.     Row() {
  23.       Column() {
  24.         Text(this.message)
  25.           .fontSize(40)
  26.           .fontWeight(FontWeight.Bold)
  27.           .margin(20)
  28.         Text('文本大小')
  29.           .fontSize(26)
  30.         TextInput({ text: '' + this.saveSize }).width('80%')
  31.           .onChange((v) => {
  32.             this.saveSize = Number(v)
  33.             this.isSave = false
  34.           })
  35.         Text('文本颜色')
  36.           .fontSize(26)
  37.         TextInput({ text: this.saveColor }).width('80%')
  38.           .onChange((v) => {
  39.             this.saveColor = v
  40.             this.isSave = false
  41.           })
  42.         Text(this.isSave ? '已保存数据' : '暂未保存').fontSize(20)
  43.         Button("保存")
  44.           .onClick(() => {
  45.             // 保存大小和颜色样式
  46.             PrefUtil.saveFontStyle(this.saveSize, this.saveColor)
  47.             this.isSave = true
  48.           }).width('60%').margin({ top: 10 })
  49.         Button("恢复默认值")
  50.           .onClick(() => {
  51.             this.saveSize = defaultSize
  52.             this.saveColor = defaultColor
  53.             this.isSave = false
  54.           }).width('60%').margin({ top: 10 })
  55.         Text('我是首选项存储文本')
  56.           .fontSize(this.saveSize)
  57.           .fontColor(Number(this.saveColor))
  58.           .margin({ top: 20 })
  59.           .textAlign(TextAlign.Center)
  60.       }
  61.       .width('100%')
  62.     }.alignItems(VerticalAlign.Top)
  63.     .height('100%')
  64.   }
  65. }
复制代码
二、关系型数据存储

概念及访问机制

   关系型数据存储(RelationalStore):提供了关系型数据库的增删改查、加密、备份以及订阅关照等,关系型数据库是以二维表的形式进行存储数据的。支持本地存储和分布式存储,通过请DatamgrService实现分布式跨设备数据同步。
         关系型数据库(Relational Database,RDB)是基于关系模子组织管理数据的数据库。关系型数据库中一样平常包含若干个二维的数据表,每个表中以行和列的形式存储数据。 鸿蒙关系型数据存储底层利用SQLite作为长期化存储引擎,支持SQLite的全部数据库特性,包括事务、索引、视图、触发器、外键、参数化查询和预编译SQL语句等。
       鸿蒙关系型数据存储框架实现了对底层SQLite数据进一步封装,对上层提供通用、美满且高效操纵接口,包括一系列的增、删、改、查等。访问机制如图所示:

 代码示例

由于代码篇幅较大,下面附上代码所在。
源代码所在:https://github.com/Sandyroys/RDBDemo.git

部分:关键代码
  1. class UserAPI {
  2.   //UserAPI 类初始化时,设置表名、列名、创建表的SQL语句,并创建 Rdb 实例来管理数据库连接。
  3.   private tableName: string = ''
  4.   private columns: Array<string> = []
  5.   private rdb: Rdb | null = null
  6.   private sql_create_table = ''
  7.   constructor( ) {
  8.     this.tableName = 'user'
  9.     this.columns = ['id', 'name', 'sex', 'age', 'tel']
  10.     this.sql_create_table = 'CREATE TABLE IF NOT EXISTS '
  11.       + this.tableName + '('
  12.       + 'id INTEGER PRIMARY KEY AUTOINCREMENT, '
  13.       + 'name TEXT NOT NULL, '
  14.       + 'sex TEXT, '
  15.       + 'age INTEGER, '
  16.       + 'tel TEXT)';
  17.     this.rdb = new Rdb(this.sql_create_table)
  18.     this.rdb.getRdbStore()
  19.   }
  20.   // 插入数据
  21.   insertUser(user:User) {
  22.     const valueBucket:relationalStore.ValuesBucket = JSON.parse(JSON.stringify(user));
  23.     if(this.rdb?.rdbStore!=null)
  24.     {
  25.       this.rdb.rdbStore.insert(this.tableName, valueBucket, (err, ret) => {
  26.         console.log('insert done: ' + ret);
  27.         promptAction.showToast({ message: '添加用户成功!' });
  28.       });
  29.     }
  30.   }
  31.   // 根据用户名查询用户信息
  32.   async queryUserByName(name:string) {
  33.     let resultList:ArrayList<User> | null = null;
  34.     let predicates = new relationalStore.RdbPredicates(this.tableName);
  35.     predicates.equalTo('name', name);
  36.     let ret = await this.queryFromDB(predicates);
  37.     if( ret!=null )
  38.     {
  39.       resultList = this.getListFromResultSet(ret);
  40.     }
  41.     return resultList;
  42.   }
  43.   // 查询全部用户信息
  44.   async queryUserAll() {
  45.     let resultList:ArrayList<User> | null = null;
  46.     let predicates = new relationalStore.RdbPredicates(this.tableName);
  47.     let ret:relationalStore.ResultSet | null = await this.queryFromDB(predicates);
  48.     if( ret!=null )
  49.     {
  50.       resultList = this.getListFromResultSet(ret);
  51.       console.info("=====>"+resultList.convertToArray().toString());
  52.     }
  53.     return resultList;
  54.   }
  55.   // 根据条件查询数据库
  56.   async queryFromDB( predicates:relationalStore.RdbPredicates ) {
  57.     let resultList:relationalStore.ResultSet | null = null;
  58.     if( this.rdb?.rdbStore!=null )
  59.     {
  60.       let promiseQuery = this.rdb.rdbStore.query(predicates, this.columns);
  61.       await promiseQuery.then((resultSet) => {
  62.         resultList = resultSet;
  63.       }).catch((err:object) => {
  64.         console.log("query err" + JSON.stringify(err));
  65.       });
  66.     }
  67.     return resultList;
  68.   }
  69.   // 将查询到的结果封装用户列表
  70.   getListFromResultSet( resultSet:relationalStore.ResultSet ) {
  71.     let userList:ArrayList<User> = new ArrayList<User>();
  72.     for (let i = 0; i < resultSet.rowCount; i++) {
  73.       resultSet.goToNextRow();
  74.       let user = new User(
  75.       resultSet.getString(resultSet.getColumnIndex('name')),
  76.       resultSet.getString(resultSet.getColumnIndex('sex')),
  77.       resultSet.getLong(resultSet.getColumnIndex('age')),
  78.       resultSet.getString(resultSet.getColumnIndex('tel')),
  79.       resultSet.getLong(resultSet.getColumnIndex('id')) );
  80.       userList.add(user);
  81.     }
  82.     return userList;
  83.   }
  84.   // 删除全部数据
  85.   async deleteAll() {
  86.     let result:number = 0;
  87.     let predicates = new relationalStore.RdbPredicates(this.tableName);
  88.     if(this.rdb?.rdbStore!=null)
  89.     {
  90.       await this.rdb.rdbStore.delete(predicates).then((rows) => {
  91.         result = rows;
  92.         promptAction.showToast({ message: '删除数据,rows:' + rows });
  93.       });
  94.     }
  95.     return result
  96.   }
  97. }
复制代码
三、总结 

在鸿蒙开发中,首选项存储和关系型数据存储是两种紧张的数据长期化办理方案。以下是对这两种存储方式的总结:
首选项存储(Preferences)


  • 功能特点

    • 首选项存储提供轻量级配置数据的长期化本领,适用于保存应用配置信息和用户偏好设置等。
    • 它支持订阅数据变化的关照本领,但不支持分布式同步。
    • 数据以文本形式保存在设备中,全量加载到内存中,因此访问速率快、效率高。
    • 得当存储少量简单数据,不得当存储大量数据。

  • 利用场景

    • 适用于存储小型配置项数据,例如应用的用户个性化设置(字体巨细、是否开启夜间模式等)。
    • 发起存储的数据不凌驾一万条,以避免在内存方面产生较大的开销。

  • 技术限定

    • Key键为string范例,长度不凌驾80个字节;Value值若为string范例,利用UTF-8编码格式,长度不凌驾8192个字节。

关系型数据存储(RelationalStore)


  • 功能特点

    • 提供关系型数据库的读写、加密、手动备份以及订阅关照的本领。
    • 可以运行自定义的SQL语句来满意复杂业务场景的必要。
    • 适用于存储复杂的数据结构,如应用内部的关系型数据。

  • 利用场景

    • 广泛用于应用中的关系型数据的处置处罚,包括增、删、改、查等操纵。
    • 得当必要数据完备性和一致性保障的场景。

  • 技术细节

    • 基于SQLite组件,提供了一套完备的对本地数据库进行管理的机制。
    • 支持基本数据范例:number、string、二进制范例数据、boolean。发起一条数据不要凌驾2M,超出该巨细大概导致插入乐成但读取失败。

总结来说,首选项存储得当轻量级的数据长期化需求,而关系型数据存储则适用于必要复杂查询和数据完备性保障的场景。开发者可以根据应用的具体需求选择合适的存储方案。


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

本帖子中包含更多资源

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

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

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

本版积分规则

杀鸡焉用牛刀

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