Android DataStore:安全存储和轻松管理数据
关于作者:CSDN内容合伙人、技术专家, 从零开始做日活千万级APP。
专注于分享各领域原创系列文章 ,擅长java后端、移动开发、人工智能等,希望大家多多支持。
目录
- 一、导读
- 二、概览
- 三、使用
- 3.1 Preferences DataStore
- 添加依赖
- 数据读写
- 3.2 ProtoDataStore
- 添加依赖
- 数据读写
- 3.3、在同步代码中使用 DataStore
- 3.4、在多进程代码中使用 DataStore
- 四、DataStore & MMKV
- 五、 推荐阅读

一、导读
我们继续总结学习Java基础知识,温故知新。
二、概览
DataStore 是一种用于 Android 应用程序数据存储的新的推荐方式。
它是在 Android Jetpack 组件中引入的,旨在替代 SharedPreferences,并提供更强大、易于使用的 API。
DataStore 基于 Kotlin 协程和 Flow 构建而成, 提供了一种类型安全且异步的数据存储解决方案。
相比于 SharedPreferences,DataStore 具有以下优点:
-
异步操作:DataStore 提供了异步的读写操作,避免了阻塞主线程的问题。这使得在读取和写入数据时,应用程序可以更好地保持响应性能。
-
类型安全:DataStore 支持使用协议缓冲区(Protocol Buffers)来定义数据模型,这样可以确保在编译时进行类型检查。数据模型的更改不会导致运行时错误,而是在编译时进行检测。
-
支持多种数据类型:DataStore 支持存储不同类型的数据,包括原始类型、对象或自定义类。
-
数据一致性:DataStore 提供了一致性和安全性保证,保证在多个写入操作中的数据一致性。
-
流式数据访问:DataStore 支持使用流(Flow)来访问数据,使得可以轻松地观察数据的变化并进行相应的更新。
DataStore 提供了两个主要的实现方式:PreferencesDataStore 和 ProtoDataStore。
PreferencesDataStore 适用于存储简单的数据类型,使用键值对来存储数据。
ProtoDataStore 则使用 Protocol Buffers 定义数据模型,并支持存储更复杂的数据结构(类型化对象)。
三、使用
3.1 Preferences DataStore
适用于存储简单的数据类型,使用键值对来存储数据
添加依赖
// Preferences DataStore (SharedPreferences like APIs)dependencies {implementation "androidx.datastore:datastore-preferences:1.0.0"// optional - RxJava2 supportimplementation "androidx.datastore:datastore-preferences-rxjava2:1.0.0"// optional - RxJava3 supportimplementation "androidx.datastore:datastore-preferences-rxjava3:1.0.0"}// Alternatively - use the following artifact without an Android dependency.dependencies {implementation "androidx.datastore:datastore-preferences-core:1.0.0"}
数据读写
RxDataStore<Preferences> dataStore =new RxPreferenceDataStoreBuilder(context, /*name=*/ "settings").build();Preferences.Key<Integer> EXAMPLE_COUNTER = PreferencesKeys.int("example_counter");Flowable<Integer> exampleCounterFlow = dataStore.data().map(prefs -> prefs.get(EXAMPLE_COUNTER));Single<Preferences> updateResult = dataStore.updateDataAsync(prefsIn -> {MutablePreferences mutablePreferences = prefsIn.toMutablePreferences();Integer currentInt = prefsIn.get(INTEGER_KEY);mutablePreferences.set(INTEGER_KEY, currentInt != null ? currentInt + 1 : 1);return Single.just(mutablePreferences);
});
// The update is completed once updateResult is completed.
3.2 ProtoDataStore
使用 Protocol Buffers 定义数据模型,并支持存储更复杂的数据结构
添加依赖
// Typed DataStore (Typed API surface, such as Proto)dependencies {implementation "androidx.datastore:datastore:1.0.0"// optional - RxJava2 supportimplementation "androidx.datastore:datastore-rxjava2:1.0.0"// optional - RxJava3 supportimplementation "androidx.datastore:datastore-rxjava3:1.0.0"}// Alternatively - use the following artifact without an Android dependency.dependencies {implementation "androidx.datastore:datastore-core:1.0.0"}
数据读写
Proto DataStore 要求在 app/src/main/proto/ 目录的 proto 文件中保存预定义的架构。
此架构用于定义在 Proto DataStore 中保存的对象的类型。
syntax = "proto3";option java_package = "com.example.application";
option java_multiple_files = true;message Settings {int32 example_counter = 1;
}
private static class SettingsSerializer implements Serializer<Settings> {@Overridepublic Settings getDefaultValue() {Settings.getDefaultInstance();}@Overridepublic Settings readFrom(@NotNull InputStream input) {try {return Settings.parseFrom(input);} catch (exception: InvalidProtocolBufferException) {throw CorruptionException(“Cannot read proto.”, exception);}}@Overridepublic void writeTo(Settings t, @NotNull OutputStream output) {t.writeTo(output);}
}RxDataStore<Byte> dataStore =new RxDataStoreBuilder<Byte>(context, /* fileName= */ "settings.pb", new SettingsSerializer()).build();Flowable<Integer> exampleCounterFlow =dataStore.data().map(settings -> settings.getExampleCounter());Single<Settings> updateResult = dataStore.updateDataAsync(currentSettings ->Single.just(currentSettings.toBuilder().setExampleCounter(currentSettings.getExampleCounter() + 1).build()));
3.3、在同步代码中使用 DataStore
DataStore 的主要优势之一是异步 API,但可能不一定始终能将周围的代码更改为异步代码。如果您使用的现有代码库采用同步磁盘 I/O,或者您的依赖项不提供异步 API,就可能出现这种情况。
Kotlin 协程提供 runBlocking() 协程构建器,以帮助消除同步与异步代码之间的差异。您可以使用 runBlocking() 从 DataStore 同步读取数据。RxJava 在 Flowable 上提供阻塞方法。以下代码会阻塞发起调用的线程,直到 DataStore 返回数据:
Settings settings = dataStore.data().blockingFirst();dataStore.data().first().subscribe();
这样,DataStore 可以异步读取数据并将其缓存在内存中。以后使用 runBlocking() 进行同步读取的速度可能会更快,或者如果初始读取已经完成,可能也可以完全避免磁盘 I/O 操作。
- 请尽可能避免在 DataStore 数据读取时阻塞线程。阻塞界面线程可能会导致 ANR 或界面卡顿,而阻塞其他线程可能会导致死锁。
3.4、在多进程代码中使用 DataStore
- DataStore 多进程功能目前仅在 1.1.0 Alpha 版中提供
为了能够在不同进程中使用 DataStore,需要使用 MultiProcessDataStoreFactory 构造 DataStore 对象。
val dataStore: DataStore<Settings> = MultiProcessDataStoreFactory.create(serializer = SettingsSerializer(),produceFile = {File("${context.cacheDir.path}/myapp.preferences_pb")}
)
四、DataStore & MMKV
看一组数据对比,图片来源于MMKV 开源网站


至于如何使用就不描述了,非常简单。
个人感觉 DataStore 没有 MMKV 好用,推荐使用 MMKV,但是各有优劣吧。
jetpack 官网
datastore
五、 推荐阅读
Java 专栏
SQL 专栏
数据结构与算法
Android学习专栏
相关文章:
Android DataStore:安全存储和轻松管理数据
关于作者:CSDN内容合伙人、技术专家, 从零开始做日活千万级APP。 专注于分享各领域原创系列文章 ,擅长java后端、移动开发、人工智能等,希望大家多多支持。 目录 一、导读二、概览三、使用3.1 Preferences DataStore添加依赖数据读…...
opencv进阶12-EigenFaces 人脸识别
EigenFaces 通常也被称为 特征脸,它使用主成分分析(Principal Component Analysis,PCA) 方法将高维的人脸数据处理为低维数据后(降维),再进行数据分析和处理,获取识别结果。 基本原理…...
The internal rate of return (IRR)
内部收益率 NPV(Net Present Value)_spencer_tseng的博客-CSDN博客...
半导体自动化专用静电消除器主要由哪些部分组成
半导体自动化专用静电消除器是一种用于消除半导体生产过程中的静电问题的设备。由于半导体制造过程中对静电的敏感性,静电可能会对半导体器件的质量和可靠性产生很大的影响,甚至造成元件损坏。因此,半导体生产中采用专用的静电消除器是非常重…...
【C++入门到精通】C++入门 —— deque(STL)
阅读导航 前言一、deque简介1. 概念2. 特点 二、deque使用1. 基本操作(增、删、查、改)2. 底层结构 三、deque的缺陷四、 为什么选择deque作为stack和queue的底层默认容器总结温馨提示 前言 文章绑定了VS平台下std::deque的源码,大家可以下载…...
Codeforces Round 893 (Div. 2) D.Trees and Segments
原题链接:Problem - D - Codeforces 题面: 大概意思就是让你在翻转01串不超过k次的情况下,使得a*(0的最大连续长度)(1的最大连续长度)最大(1<a<n)。输出n个数&…...
SpringBoot + Vue 前后端分离项目 微人事(九)
职位管理后端接口设计 在controller包里面新建system包,再在system包里面新建basic包,再在basic包里面创建PositionController类,在定义PositionController类的接口的时候,一定要与数据库的menu中的url地址到一致,不然…...
【业务功能篇71】Cglib的BeanCopier进行Bean对象拷贝
选择Cglib的BeanCopier进行Bean拷贝的理由是, 其性能要比Spring的BeanUtils,Apache的BeanUtils和PropertyUtils要好很多, 尤其是数据量比较大的情况下。 BeanCopier的主要作用是将数据库层面的Entity转化成service层的POJO。BeanCopier其实已…...
让eslint的错误信息显示在项目界面上
1.需求描述 效果如下 让eslint中的错误,显示在项目界面上 2.问题解决 1.安装 vite-plugin-eslint 插件 npm install vite-plugin-eslint --save-dev2.配置插件 // vite.config.js import { defineConfig } from vite import vue from vitejs/plugin-vue import e…...
手摸手带你实现一个开箱即用的Node邮件推送服务
目录 编辑 前言 准备工作 邮箱配置 代码实现 服务部署 使用效果 题外话 写在最后 相关代码: 前言 由于邮箱账号和手机号的唯一性,通常实现验证码的校验时比较常用的两种方式是手机短信推送和邮箱推送,此外,邮件推送服…...
【Linux网络】网络编程套接字 -- 基于socket实现一个简单UDP网络程序
认识端口号网络字节序处理字节序函数 htonl、htons、ntohl、ntohs socketsocket编程接口sockaddr结构结尾实现UDP程序的socket接口使用解析socket处理 IP 地址的函数初始化sockaddr_inbindrecvfromsendto 实现一个简单的UDP网络程序封装服务器相关代码封装客户端相关代码实验结…...
Python学习笔记第六十四天(Matplotlib 网格线)
Python学习笔记第六十四天 Matplotlib 网格线普通网格线样式网格线 后记 Matplotlib 网格线 我们可以使用 pyplot 中的 grid() 方法来设置图表中的网格线。 grid() 方法语法格式如下: matplotlib.pyplot.grid(bNone, whichmajor, axisboth, )参数说明:…...
机器学习与模式识别3(线性回归与逻辑回归)
一、线性回归与逻辑回归简介 线性回归主要功能是拟合数据,常用平方误差函数。 逻辑回归主要功能是区分数据,找到决策边界,常用交叉熵。 二、线性回归与逻辑回归的实现 1.线性回归 利用回归方程对一个或多个特征值和目标值之间的关系进行建模…...
vue启动配置npm run serve,动态环境变量,根据不同环境访问不同域名
首先创建不同环境的配置文件,比如域名和一些常量,创建一个env文件,先看看文件目录 env.dev就是dev环境的域名,.test就是test环境域名,其他同理,然后配置package.json文件 {"name": "require-admin&qu…...
HTML <strike> 标签
HTML5 中不支持 <strike> 标签在 HTML 4 中用于定义删除线文本。 定义和用法 <strike> 标签可定义加删除线文本定义。 浏览器支持 元素ChromeIEFirefoxSafariOpera<strike>YesYesYesYesYes 所有浏览器都支持 <strike> 标签。 HTML 与 XHTML 之间…...
数学建模-模型详解(1)
规划模型 线性规划模型: 当涉及到线性规划模型实例时,以下是一个简单的示例: 假设我们有两个变量 x 和 y,并且我们希望最大化目标函数 Z 5x 3y,同时满足以下约束条件: x > 0y > 02x y < 10…...
MySQL 数据库表的基本操作
一、数据库表概述 在数据库中,数据表是数据库中最重要、最基本的操作对象,是数据存储的基本单位。数据表被定义为列的集合,数据在表中是按照行和列的格式来存储的。每一行代表一条唯一的记录,每一列代表记录中的一个域。 二、数…...
企业微信电脑端开启chrome调试
首先: Mac端调试开启的快捷键:control shift command d Window端调试开启的快捷键: control shift alt d 这边以Mac为例,我们可以在电脑顶部看到调试的入口: 然后我们点击 『浏览器、webView相关』菜单,勾选上…...
Maven官网下载配置新仓库
1.Maven的下载 Maven的官网地址:Maven – Download Apache Maven 点击Download,查找 Files下的版本并下载如下图: 2.Maven的配置 自己在D盘或者E盘创建一个文件夹,作为本地仓库,存放项目依赖。 将下载好的zip文件进行解…...
银河麒麟V10 达梦安装教程
安装前先准备要安装包,包需要需要区分X86和arm架构。 版本为:dm8_20230419_FTarm_kylin10_sp1_64.iso 达梦数据库下载地址: https://www.aliyundrive.com/s/Qm7Es5BQM5U 第一步创建用户 su - root 1. 创建安装用户组 dminstall。 groupad…...
OliveTin高级功能指南:定时任务、文件监控和实体动态更新
OliveTin高级功能指南:定时任务、文件监控和实体动态更新 【免费下载链接】OliveTin OliveTin gives safe and simple access to predefined shell commands from a web interface. 项目地址: https://gitcode.com/gh_mirrors/ol/OliveTin OliveTin是一个强…...
LFM2.5-1.2B-Thinking-GGUF开源可部署:自主可控轻量模型替代方案深度评测
LFM2.5-1.2B-Thinking-GGUF开源可部署:自主可控轻量模型替代方案深度评测 1. 模型概述 LFM2.5-1.2B-Thinking-GGUF是Liquid AI推出的轻量级文本生成模型,专为低资源环境优化设计。该模型采用GGUF格式存储,配合llama.cpp运行时,能…...
QQ音乐下载的歌曲怎么导出来?分享我的FFMpeg自动化处理脚本(附Win/Mac命令)
用FFMpeg实现QQ音乐文件自动化处理:跨平台脚本全解析 每次从QQ音乐下载的歌曲文件总是带着各种限制——加密格式只能在特定播放器打开,专辑封面无法显示,批量处理更是让人头疼。作为一个整理过上千首音乐文件的资深用户,我摸索出…...
Windows Defender Remover:彻底移除Windows安全组件的终极解决方案
Windows Defender Remover:彻底移除Windows安全组件的终极解决方案 【免费下载链接】windows-defender-remover A tool which is uses to remove Windows Defender in Windows 8.x, Windows 10 (every version) and Windows 11. 项目地址: https://gitcode.com/gh…...
Mi-Create终极指南:三步快速创建专属小米手表表盘
Mi-Create终极指南:三步快速创建专属小米手表表盘 【免费下载链接】Mi-Create Unofficial watchface creator for Xiaomi wearables ~2021 and above 项目地址: https://gitcode.com/gh_mirrors/mi/Mi-Create 想要为你的小米手表打造独一无二的个性化表盘吗&…...
颠覆级工具:Unity游戏自动翻译与游戏本地化全攻略
颠覆级工具:Unity游戏自动翻译与游戏本地化全攻略 【免费下载链接】XUnity.AutoTranslator 项目地址: https://gitcode.com/gh_mirrors/xu/XUnity.AutoTranslator 在全球化游戏市场中,语言障碍已成为制约玩家体验与开发者用户增长的核心痛点。XU…...
分支限界法 vs 回溯法:5个关键区别和实际应用场景对比
分支限界法与回溯法:核心差异与工程实践指南 在解决复杂组合优化问题时,算法选择往往决定了程序的执行效率。当面对NP难问题时,两种经典算法——分支限界法和回溯法——常被开发者拿来比较。本文将深入剖析这两种算法的本质区别,并…...
Realistic Vision V5.1虚拟摄影棚效果验证:专业摄影师盲测准确率87.3%
Realistic Vision V5.1虚拟摄影棚效果验证:专业摄影师盲测准确率87.3% 1. 项目概述 Realistic Vision V5.1虚拟摄影棚是基于当前最先进的写实风格生成模型开发的本地化摄影工具。经过深度优化后,该工具能够生成与专业单反相机拍摄效果相媲美的人像作品…...
MIXBOX vs MisstarTools:小米路由器插件管理工具深度对比与选择建议
MIXBOX vs MisstarTools:小米路由器插件生态深度解析与实战指南 当小米路由器遇上第三方插件管理工具,整个设备的可玩性会瞬间提升几个层级。作为长期折腾智能路由的玩家,我几乎试遍了市面上所有主流的小米路由器增强方案,其中最让…...
24小时运行验证:OpenClaw+ollama-QwQ-32B自动化监控脚本稳定性测试
24小时运行验证:OpenClawollama-QwQ-32B自动化监控脚本稳定性测试 1. 项目背景与目标设定 去年冬天的一个深夜,我被手机警报惊醒——某个关键商品的价格突然跌破了我的心理预期。手忙脚乱登录电商平台时,优惠早已结束。这次经历让我意识到&…...
