HarmonyOS7 数据持久化:Preferences 和 RDB 到底选哪个?
文章目录前言两种方案定位Preferences 实战轻量 KV 存储完整代码API 逐个讲解使用示例RDB 实战关系型数据库 CRUD完整代码SQL 和 API 讲解性能对比数据选型建议写在最后前言每次做新项目数据持久化这块我都会纠结——用 Preferences 还是 RDB选轻量了不够用选重量了又杀鸡用牛刀。踩了几次坑之后我总算搞明白了这俩的边界。今天把经验分享一下帮你少走弯路。存个用户设置、缓存个登录状态用 Preferences 三行代码搞定。但要存聊天记录、商品列表这种有关系的复杂数据Preferences 就撑不住了得上 RDB。问题在于很多人不知道什么时候该选哪个干脆全用 RDB结果简单配置项也要写 SQL累不累两种方案定位先看核心区别一张表搞定维度PreferencesRDB (关系型数据库)底层KV 键值对文件SQLite数据结构Key-Value表、行、列适合数据量 1万条轻量级无硬限制百万级都行查询能力只能按 Key 查支持 SQL 全量查询事务支持无有begin/commit/rollback数据类型number/string/boolean/Array任意 SQL 类型并发安全不支持多进程支持学习成本低5 分钟上手中要会写 SQL典型场景用户设置、登录标记、引导状态聊天记录、商品数据、订单信息|Key 限制| 长度 ≤ 1024 字节 | 无此限制 ||Value 限制| string ≤ 16MB | 无此限制 ||缓存机制| 内存缓存读取极快 | 无内存缓存 |一句话总结简单配置用 Preferences复杂关系用 RDB。Preferences 实战轻量 KV 存储场景保存用户设置主题、字号、通知开关。完整代码import{preferences}fromkit.ArkDataimport{Context}fromkit.AbilityKitconstPREF_NAMEuser_settingsclassPrefManager{privatepref:preferences.Preferences|nullnullasyncinit(context:Context){this.prefawaitpreferences.getPreferences(context,PREF_NAME)}asyncput(key:string,value:preferences.ValueType){if(!this.pref)returnawaitthis.pref.put(key,value)awaitthis.pref.flush()}asyncget(key:string,defaultValue:preferences.ValueType):Promisepreferences.ValueType{if(!this.pref)returndefaultValuereturnawaitthis.pref.get(key,defaultValue)}asyncremove(key:string){if(!this.pref)returnawaitthis.pref.delete(key)awaitthis.pref.flush()}asyncclear(){if(!this.pref)returnawaitthis.pref.clear()awaitthis.pref.flush()}}exportconstprefManagernewPrefManager()API 逐个讲解getPreferences(context, name)根据 name 获取 Preferences 实例。同一个 name 全局只有一个实例系统会缓存。put(key, value)写入键值对。数据先写到内存缓存调用flush()才真正写入磁盘。flush()这个必须调不调 flush应用崩溃数据就丢了。put之后紧跟flush是标准操作。get(key, defaultValue)读取数据。没有这个 key 就返回默认值不会报错。delete(key)删除指定 key也要跟flush()。clear()清空所有数据慎用。使用示例// 初始化在 EntryAbility.onCreate 中awaitprefManager.init(this.context)// 存储用户设置awaitprefManager.put(theme,dark)awaitprefManager.put(fontSize,18)awaitprefManager.put(notifications,true)// 读取constthemeawaitprefManager.get(theme,light)asstringconstfontSizeawaitprefManager.get(fontSize,14)asnumberconstnotifyawaitprefManager.get(notifications,false)asboolean就这么简单。存配置项、开关、标记Preferences 真的够了。RDB 实战关系型数据库 CRUD场景做一个记账 App需要存账单数据金额、分类、日期、备注。完整代码import{relationalStore}fromkit.ArkDataimport{Context}fromkit.AbilityKitconstDB_NAMEbill.dbconstSTORE_CONFIG:relationalStore.StoreConfig{name:DB_NAME,securityLevel:relationalStore.SecurityLevel.S1}constCREATE_TABLE_SQLCREATE TABLE IF NOT EXISTS bills ( id INTEGER PRIMARY KEY AUTOINCREMENT, amount REAL NOT NULL, category TEXT NOT NULL, date TEXT NOT NULL, note TEXT, created_at INTEGER )classBillDB{privaterdbStore:relationalStore.RdbStore|nullnullasyncinit(context:Context){this.rdbStoreawaitrelationalStore.getRdbStore(context,STORE_CONFIG)awaitthis.rdbStore.executeSql(CREATE_TABLE_SQL)}asyncinsert(bill:BillItem):Promisenumber{if(!this.rdbStore)return-1constvalues:relationalStore.ValuesBucket{amount:bill.amount,category:bill.category,date:bill.date,note:bill.note||,created_at:Date.now()}constrowIdawaitthis.rdbStore.insert(bills,values)returnrowId}asyncqueryByDate(startDate:string,endDate:string):PromiseBillItem[]{if(!this.rdbStore)return[]constpredicatesnewrelationalStore.RdbPredicates(bills)predicates.between(date,startDate,endDate).orderByDesc(date)constresultSetawaitthis.rdbStore.query(predicates)returnthis.resultSetToList(resultSet)}asyncdeleteById(id:number):Promisenumber{if(!this.rdbStore)return0constpredicatesnewrelationalStore.RdbPredicates(bills)predicates.equalTo(id,id)returnawaitthis.rdbStore.delete(predicates)}asyncupdateById(id:number,bill:PartialBillItem):Promisenumber{if(!this.rdbStore)return0constvalues:relationalStore.ValuesBucket{}if(bill.amount!undefined)values.amountbill.amountif(bill.category!undefined)values.categorybill.categoryif(bill.note!undefined)values.notebill.noteconstpredicatesnewrelationalStore.RdbPredicates(bills)predicates.equalTo(id,id)returnawaitthis.rdbStore.update(values,predicates)}privateresultSetToList(resultSet:relationalStore.ResultSet):BillItem[]{constlist:BillItem[][]if(resultSet.rowCount0){resultSet.close()returnlist}resultSet.goToFirstRow()do{constbill:BillItem{id:resultSet.getLong(resultSet.getColumnIndex(id)),amount:resultSet.getDouble(resultSet.getColumnIndex(amount)),category:resultSet.getString(resultSet.getColumnIndex(category)),date:resultSet.getString(resultSet.getColumnIndex(date)),note:resultSet.getString(resultSet.getColumnIndex(note))}list.push(bill)}while(resultSet.goToNextRow())resultSet.close()returnlist}}interfaceBillItem{id?:numberamount:numbercategory:stringdate:stringnote?:string}exportconstbillDBnewBillDB()SQL 和 API 讲解建表 SQLINTEGER PRIMARY KEY AUTOINCREMENT主键自增插入时不用手动指定 idREAL NOT NULL金额用浮点类型不允许为空TEXT NOT NULL分类和日期用字符串不允许为空TEXT备注可空CRUD 操作增insert(tableName, valuesBucket)—— valuesBucket 是键值对key 对应列名查RdbPredicates构建查询条件between做范围查询equalTo做精确匹配改update(valuesBucket, predicates)—— 只更新 valuesBucket 里的字段删delete(predicates)—— 按 predicates 条件删除ResultSet 解析这是 RDB 最烦的部分。query返回ResultSet要手动遍历、按列名取值、最后close()。忘 close 会内存泄漏我踩过。性能对比数据实测数据1000 条记录中端手机操作PreferencesRDB写入 1 条 1ms2-5ms读取 1 条 1ms3-8ms写入 100 条10-20ms50-100ms条件查询 100 条不支持10-30ms全量查询 1000 条不现实50-100msPreferences 读写速度碾压 RDB因为数据全在内存里。但一旦涉及条件查询、排序、关联Preferences 直接歇菜。选型建议别纠结了按这张决策表选你的需求选哪个理由用户设置、开关、标记Preferences轻量快速KV 就够了登录态缓存Preferences就一个 token用啥数据库引导页是否展示过Preferences一个 boolean 搞定购物车 50 条Preferences数据少简单购物车 50 条RDB数据多了需要筛选排序聊天记录RDB数据量大需要按时间查询商品数据RDB需要分类筛选排序订单记录RDB多表关联复杂查询收藏列表 100 条RDB需要分页查询我的原则能 Preferences 就不 RDB数据一复杂就别硬撑。两个方案也不冲突可以在同一个项目里都用——设置用 Preferences业务数据用 RDB各司其职。写在最后数据持久化没有银弹选型就是看场景。Preferences 是一把快刀削苹果削黄瓜都好用但别拿它砍树。RDB 是电锯砍树一流削苹果就太费劲了。搞清楚自己要存什么、怎么查、数据量多大答案就出来了。

相关新闻

艺术涂料执行标准?专家告诉你真相

艺术涂料执行标准?专家告诉你真相

一、执行标准到底是什么执行标准是国家或行业对产品性能、安全、环保的硬性要求,比如耐洗刷、附着力、VOC限量等,企业必须按它生产并标注。它像产品的“及格线”,告诉你这款料至少该达到什么水平。但“有标准”不等于“高标准”,不…

2026/7/23 22:44:31 阅读更多 →
DeepSeek专家模式突破对话上限技巧,无缝衔接新对话!

DeepSeek专家模式突破对话上限技巧,无缝衔接新对话!

各位有没有在使用DeepSeek中,尤其是专家模式深度思考,出现“对话已达上限”的提示? 这篇文章我就分享如何解决这个问题。这也是我最开始十分头疼又无法逾越的鸿沟! 当你的DeepSeek在专家模式深度思考的情况下出现“对话已达上限”…

2026/7/23 22:43:30 阅读更多 →
Mailpit介绍(本地开发和自动化测试邮件沙箱)本地邮件服务、本地SMTP服务器、1025端口、8025端口、Chaos功能、SMTP Relay(SMTP 中继)、MailHog

Mailpit介绍(本地开发和自动化测试邮件沙箱)本地邮件服务、本地SMTP服务器、1025端口、8025端口、Chaos功能、SMTP Relay(SMTP 中继)、MailHog

● Mailpit 不需要注册任何账号——它和 Resend 是完全不同的两类东西:Mailpit 是一个"假邮箱服务器",只在你本机跑。它是一个开源的 Docker 容器(我已经加到 docker-compose.yml,用 profile门控,只在本地开…

2026/7/23 22:43:30 阅读更多 →

最新新闻

2026最新指标测评|企业引入AI数字员工,团队如何筛选适配的服务商?

2026最新指标测评|企业引入AI数字员工,团队如何筛选适配的服务商?

随着大模型和AI Agent进入企业业务,越来越多公司开始尝试用AI辅助客服、销售、内容运营和经营分析。但进入实际部署阶段后,企业往往会发现:能对话、能生成内容,不等于能理解业务、执行任务并进入现有工作流程。 普通AI工具不了解…

2026/7/23 22:56:38 阅读更多 →
协程与 Android 生命周期:该何时取消、何时保留

协程与 Android 生命周期:该何时取消、何时保留

文章目录第 1 章 生命周期为什么约束协程第 2 章 lifecycleScope:短 UI 副作用踩坑第 3 章 viewModelScope 与 Fragment 取 VM踩坑第 4 章 repeatOnLifecycle:后台停止收集踩坑第 5 章 取消链:从 UI 到 Repository第 6 章 SupervisorJob 与并…

2026/7/23 22:56:38 阅读更多 →
机床测头撞了/测针断了,还有救吗?——分等级损伤评估与维修成本指南

机床测头撞了/测针断了,还有救吗?——分等级损伤评估与维修成本指南

测头撞了/测针断了,还有救吗?——分等级损伤评估与维修成本指南 编号:JCE-DOCG-WBQ260615 版本:V2.1 适用范围:数控机床(CNC加工中心)在线测量测头系统 适用品牌:雷尼绍(…

2026/7/23 22:56:38 阅读更多 →
从 Kimi K3 看 AI 创业终局:四层护城河与中小团队生存路径

从 Kimi K3 看 AI 创业终局:四层护城河与中小团队生存路径

Kimi K3重磅炸场!无数AI创业者无路可走?【摘要】通用大模型参数规模与综合能力高速迭代,垂直 AI 工具正面临同质化降维冲击。通过拆解工具、效率、业务、生态四层商业护城河框架,结合技术落地实践与产业案例,为 AI 创业…

2026/7/23 22:56:38 阅读更多 →
TVP5151视频解码芯片:模拟信号转数字YCbCr 4:2:2实战指南

TVP5151视频解码芯片:模拟信号转数字YCbCr 4:2:2实战指南

1. 项目概述:从模拟到数字的桥梁在数字视频处理的世界里,我们常常面对一个看似“古老”但依然无处不在的问题:如何处理那些来自老式摄像机、录像机、游戏机甚至某些监控系统的模拟视频信号?无论是NTSC制式的“雪花”画面&#xff…

2026/7/23 22:56:38 阅读更多 →
CANNBot 实操体验:基于Ascend C的矩阵乘法算子开发

CANNBot 实操体验:基于Ascend C的矩阵乘法算子开发

目录 引言 测评结论 ✅ 核心优势 ⚠️ 待优化点 📊 效率提升效果 CANNBot 是什么? 核心能力一览 本次实操案例 第一部分:环境搭建 1.1 创建Notebook实例 1.2 安装 Node.js 18 1.3 安装 OpenCode 1.4 安装 CANNBot-Skills 第二部分&#xff1a…

2026/7/23 22:55:37 阅读更多 →

日新闻

从单点好评到指数级传播:AI副业主理人必须掌握的4层口碑渗透模型(含ROI测算表)

从单点好评到指数级传播:AI副业主理人必须掌握的4层口碑渗透模型(含ROI测算表)

更多请点击: https://intelliparadigm.com 第一章:从单点好评到指数级传播:AI副业主理人必须掌握的4层口碑渗透模型(含ROI测算表) 当AI副业主理人不再仅满足于单次服务交付,而是主动构建可复用、可裂变、可…

2026/7/23 0:00:25 阅读更多 →
AI写作开头钩子设计:为什么你的AI文案完读率不足18%?——基于2,346篇A/B测试报告的归因分析

AI写作开头钩子设计:为什么你的AI文案完读率不足18%?——基于2,346篇A/B测试报告的归因分析

更多请点击: https://codechina.net 第一章:AI写作开头钩子设计:为什么你的AI文案完读率不足18%?——基于2,346篇A/B测试报告的归因分析 在对2,346篇跨行业AI生成文案的A/B测试数据进行聚类分析后,我们发现&#xff1…

2026/7/23 0:01:26 阅读更多 →
Chitchatter完整指南:免费开源的终极点对点安全聊天工具

Chitchatter完整指南:免费开源的终极点对点安全聊天工具

Chitchatter完整指南:免费开源的终极点对点安全聊天工具 【免费下载链接】chitchatter Secure peer-to-peer chat that is serverless, decentralized, and ephemeral 项目地址: https://gitcode.com/gh_mirrors/ch/chitchatter Chitchatter是一款革命性的安…

2026/7/23 0:01:26 阅读更多 →

周新闻

Go语言静态资源打包方案对比与实践指南

Go语言静态资源打包方案对比与实践指南

1. 项目背景与核心需求在Go语言开发中,我们经常需要处理静态资源文件的打包问题。无论是Web应用的模板文件、前端资源,还是配置文件、证书等,都需要随程序一起分发。传统做法是将这些文件与编译后的二进制文件放在同一目录下,但这…

2026/7/22 8:58:19 阅读更多 →
Go语言实现高性能LDAP认证服务的架构与实践

Go语言实现高性能LDAP认证服务的架构与实践

1. 项目背景与核心价值LDAP(轻量级目录访问协议)作为企业级身份认证的黄金标准,已经服务了超过80%的财富500强公司。我在金融科技领域实施统一认证体系时,发现传统Java方案存在启动慢、内存占用高等痛点。而Go语言凭借其协程并发模…

2026/7/22 19:43:43 阅读更多 →
【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

更多请点击: https://intelliparadigm.com 第一章:AI面试官实战指南的核心价值与适用场景 AI面试官并非替代人类HR的“黑箱工具”,而是以可解释、可审计、可迭代的方式,赋能招聘全链路的关键基础设施。其核心价值在于将主观经验沉…

2026/7/23 17:49:47 阅读更多 →

月新闻