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…...
React 第五十五节 Router 中 useAsyncError的使用详解
前言 useAsyncError 是 React Router v6.4 引入的一个钩子,用于处理异步操作(如数据加载)中的错误。下面我将详细解释其用途并提供代码示例。 一、useAsyncError 用途 处理异步错误:捕获在 loader 或 action 中发生的异步错误替…...
OpenLayers 可视化之热力图
注:当前使用的是 ol 5.3.0 版本,天地图使用的key请到天地图官网申请,并替换为自己的key 热力图(Heatmap)又叫热点图,是一种通过特殊高亮显示事物密度分布、变化趋势的数据可视化技术。采用颜色的深浅来显示…...
STM32+rt-thread判断是否联网
一、根据NETDEV_FLAG_INTERNET_UP位判断 static bool is_conncected(void) {struct netdev *dev RT_NULL;dev netdev_get_first_by_flags(NETDEV_FLAG_INTERNET_UP);if (dev RT_NULL){printf("wait netdev internet up...");return false;}else{printf("loc…...
vue3 字体颜色设置的多种方式
在Vue 3中设置字体颜色可以通过多种方式实现,这取决于你是想在组件内部直接设置,还是在CSS/SCSS/LESS等样式文件中定义。以下是几种常见的方法: 1. 内联样式 你可以直接在模板中使用style绑定来设置字体颜色。 <template><div :s…...
如何为服务器生成TLS证书
TLS(Transport Layer Security)证书是确保网络通信安全的重要手段,它通过加密技术保护传输的数据不被窃听和篡改。在服务器上配置TLS证书,可以使用户通过HTTPS协议安全地访问您的网站。本文将详细介绍如何在服务器上生成一个TLS证…...

IT供电系统绝缘监测及故障定位解决方案
随着新能源的快速发展,光伏电站、储能系统及充电设备已广泛应用于现代能源网络。在光伏领域,IT供电系统凭借其持续供电性好、安全性高等优势成为光伏首选,但在长期运行中,例如老化、潮湿、隐裂、机械损伤等问题会影响光伏板绝缘层…...

以光量子为例,详解量子获取方式
光量子技术获取量子比特可在室温下进行。该方式有望通过与名为硅光子学(silicon photonics)的光波导(optical waveguide)芯片制造技术和光纤等光通信技术相结合来实现量子计算机。量子力学中,光既是波又是粒子。光子本…...
C#中的CLR属性、依赖属性与附加属性
CLR属性的主要特征 封装性: 隐藏字段的实现细节 提供对字段的受控访问 访问控制: 可单独设置get/set访问器的可见性 可创建只读或只写属性 计算属性: 可以在getter中执行计算逻辑 不需要直接对应一个字段 验证逻辑: 可以…...

AirSim/Cosys-AirSim 游戏开发(四)外部固定位置监控相机
这个博客介绍了如何通过 settings.json 文件添加一个无人机外的 固定位置监控相机,因为在使用过程中发现 Airsim 对外部监控相机的描述模糊,而 Cosys-Airsim 在官方文档中没有提供外部监控相机设置,最后在源码示例中找到了,所以感…...
多模态图像修复系统:基于深度学习的图片修复实现
多模态图像修复系统:基于深度学习的图片修复实现 1. 系统概述 本系统使用多模态大模型(Stable Diffusion Inpainting)实现图像修复功能,结合文本描述和图片输入,对指定区域进行内容修复。系统包含完整的数据处理、模型训练、推理部署流程。 import torch import numpy …...