当前位置: 首页 > news >正文

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 具有以下优点:

  1. 异步操作:DataStore 提供了异步的读写操作,避免了阻塞主线程的问题。这使得在读取和写入数据时,应用程序可以更好地保持响应性能。

  2. 类型安全:DataStore 支持使用协议缓冲区(Protocol Buffers)来定义数据模型,这样可以确保在编译时进行类型检查。数据模型的更改不会导致运行时错误,而是在编译时进行检测。

  3. 支持多种数据类型:DataStore 支持存储不同类型的数据,包括原始类型、对象或自定义类。

  4. 数据一致性:DataStore 提供了一致性和安全性保证,保证在多个写入操作中的数据一致性。

  5. 流式数据访问: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:安全存储和轻松管理数据

关于作者&#xff1a;CSDN内容合伙人、技术专家&#xff0c; 从零开始做日活千万级APP。 专注于分享各领域原创系列文章 &#xff0c;擅长java后端、移动开发、人工智能等&#xff0c;希望大家多多支持。 目录 一、导读二、概览三、使用3.1 Preferences DataStore添加依赖数据读…...

opencv进阶12-EigenFaces 人脸识别

EigenFaces 通常也被称为 特征脸&#xff0c;它使用主成分分析&#xff08;Principal Component Analysis&#xff0c;PCA&#xff09; 方法将高维的人脸数据处理为低维数据后&#xff08;降维&#xff09;&#xff0c;再进行数据分析和处理&#xff0c;获取识别结果。 基本原理…...

The internal rate of return (IRR)

内部收益率 NPV(Net Present Value)_spencer_tseng的博客-CSDN博客...

半导体自动化专用静电消除器主要由哪些部分组成

半导体自动化专用静电消除器是一种用于消除半导体生产过程中的静电问题的设备。由于半导体制造过程中对静电的敏感性&#xff0c;静电可能会对半导体器件的质量和可靠性产生很大的影响&#xff0c;甚至造成元件损坏。因此&#xff0c;半导体生产中采用专用的静电消除器是非常重…...

【C++入门到精通】C++入门 —— deque(STL)

阅读导航 前言一、deque简介1. 概念2. 特点 二、deque使用1. 基本操作&#xff08;增、删、查、改&#xff09;2. 底层结构 三、deque的缺陷四、 为什么选择deque作为stack和queue的底层默认容器总结温馨提示 前言 文章绑定了VS平台下std::deque的源码&#xff0c;大家可以下载…...

Codeforces Round 893 (Div. 2) D.Trees and Segments

原题链接&#xff1a;Problem - D - Codeforces 题面&#xff1a; 大概意思就是让你在翻转01串不超过k次的情况下&#xff0c;使得a*&#xff08;0的最大连续长度&#xff09;&#xff08;1的最大连续长度&#xff09;最大&#xff08;1<a<n&#xff09;。输出n个数&…...

SpringBoot + Vue 前后端分离项目 微人事(九)

职位管理后端接口设计 在controller包里面新建system包&#xff0c;再在system包里面新建basic包&#xff0c;再在basic包里面创建PositionController类&#xff0c;在定义PositionController类的接口的时候&#xff0c;一定要与数据库的menu中的url地址到一致&#xff0c;不然…...

【业务功能篇71】Cglib的BeanCopier进行Bean对象拷贝

选择Cglib的BeanCopier进行Bean拷贝的理由是&#xff0c; 其性能要比Spring的BeanUtils&#xff0c;Apache的BeanUtils和PropertyUtils要好很多&#xff0c; 尤其是数据量比较大的情况下。 BeanCopier的主要作用是将数据库层面的Entity转化成service层的POJO。BeanCopier其实已…...

让eslint的错误信息显示在项目界面上

1.需求描述 效果如下 让eslint中的错误&#xff0c;显示在项目界面上 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邮件推送服务

目录 ​编辑 前言 准备工作 邮箱配置 代码实现 服务部署 使用效果 题外话 写在最后 相关代码&#xff1a; 前言 由于邮箱账号和手机号的唯一性&#xff0c;通常实现验证码的校验时比较常用的两种方式是手机短信推送和邮箱推送&#xff0c;此外&#xff0c;邮件推送服…...

【Linux网络】网络编程套接字 -- 基于socket实现一个简单UDP网络程序

认识端口号网络字节序处理字节序函数 htonl、htons、ntohl、ntohs socketsocket编程接口sockaddr结构结尾实现UDP程序的socket接口使用解析socket处理 IP 地址的函数初始化sockaddr_inbindrecvfromsendto 实现一个简单的UDP网络程序封装服务器相关代码封装客户端相关代码实验结…...

Python学习笔记第六十四天(Matplotlib 网格线)

Python学习笔记第六十四天 Matplotlib 网格线普通网格线样式网格线 后记 Matplotlib 网格线 我们可以使用 pyplot 中的 grid() 方法来设置图表中的网格线。 grid() 方法语法格式如下&#xff1a; matplotlib.pyplot.grid(bNone, whichmajor, axisboth, )参数说明&#xff1a…...

机器学习与模式识别3(线性回归与逻辑回归)

一、线性回归与逻辑回归简介 线性回归主要功能是拟合数据&#xff0c;常用平方误差函数。 逻辑回归主要功能是区分数据&#xff0c;找到决策边界&#xff0c;常用交叉熵。 二、线性回归与逻辑回归的实现 1.线性回归 利用回归方程对一个或多个特征值和目标值之间的关系进行建模…...

vue启动配置npm run serve,动态环境变量,根据不同环境访问不同域名

首先创建不同环境的配置文件&#xff0c;比如域名和一些常量&#xff0c;创建一个env文件,先看看文件目录 env.dev就是dev环境的域名&#xff0c;.test就是test环境域名&#xff0c;其他同理&#xff0c;然后配置package.json文件 {"name": "require-admin&qu…...

HTML <strike> 标签

HTML5 中不支持 <strike> 标签在 HTML 4 中用于定义删除线文本。 定义和用法 <strike> 标签可定义加删除线文本定义。 浏览器支持 元素ChromeIEFirefoxSafariOpera<strike>YesYesYesYesYes 所有浏览器都支持 <strike> 标签。 HTML 与 XHTML 之间…...

数学建模-模型详解(1)

规划模型 线性规划模型&#xff1a; 当涉及到线性规划模型实例时&#xff0c;以下是一个简单的示例&#xff1a; 假设我们有两个变量 x 和 y&#xff0c;并且我们希望最大化目标函数 Z 5x 3y&#xff0c;同时满足以下约束条件&#xff1a; x > 0y > 02x y < 10…...

MySQL 数据库表的基本操作

一、数据库表概述 在数据库中&#xff0c;数据表是数据库中最重要、最基本的操作对象&#xff0c;是数据存储的基本单位。数据表被定义为列的集合&#xff0c;数据在表中是按照行和列的格式来存储的。每一行代表一条唯一的记录&#xff0c;每一列代表记录中的一个域。 二、数…...

企业微信电脑端开启chrome调试

首先&#xff1a; Mac端调试开启的快捷键&#xff1a;control shift command d Window端调试开启的快捷键: control shift alt d 这边以Mac为例&#xff0c;我们可以在电脑顶部看到调试的入口&#xff1a; 然后我们点击 『浏览器、webView相关』菜单&#xff0c;勾选上…...

Maven官网下载配置新仓库

1.Maven的下载 Maven的官网地址&#xff1a;Maven – Download Apache Maven 点击Download&#xff0c;查找 Files下的版本并下载如下图&#xff1a; 2.Maven的配置 自己在D盘或者E盘创建一个文件夹&#xff0c;作为本地仓库&#xff0c;存放项目依赖。 将下载好的zip文件进行解…...

银河麒麟V10 达梦安装教程

安装前先准备要安装包&#xff0c;包需要需要区分X86和arm架构。 版本为&#xff1a;dm8_20230419_FTarm_kylin10_sp1_64.iso 达梦数据库下载地址&#xff1a; https://www.aliyundrive.com/s/Qm7Es5BQM5U 第一步创建用户 su - root 1. 创建安装用户组 dminstall。 groupad…...

Python操作MongoDB数据库

安装MongoDB库 pip install pymongopython 代码 Author: tkhywang 2810248865qq.com Date: 2023-08-21 10:22:30 LastEditors: tkhywang 2810248865qq.com LastEditTime: 2023-08-21 11:17:45 FilePath: \PythonProject02\MongoDB 数据库.py Description: 这是默认设置,请设置…...

《HeadFirst设计模式(第二版)》第十一章代码——代理模式

代码文件目录&#xff1a; RMI&#xff1a; MyRemote package Chapter11_ProxyPattern.RMI;import java.rmi.Remote; import java.rmi.RemoteException;public interface MyRemote extends Remote {public String sayHello() throws RemoteException; }MyRemoteClient packa…...

QT的工程文件认识

目录 1、QT介绍 2、QT的特点 3、QT模块 3.1基本模块 3.2扩展模块 4、QT工程创建 1.选择应用的窗体格式 2.设置工程的名称与路径 3.设置类名 4.选择编译器 5、QT 工程解析 xxx.pro 工程配置 xxx.h 头文件 main.cpp 主函数 xxx.cpp 文件 6、纯手工创建一个QT 工程…...

typeScript安装及TypeScript tsc 不是内部或外部命令,也不是可运行的程序或批处理文件解决办法

一、typeScript安装&#xff1a; 1、首先确定系统中已安装node, winr 输入cmd 打开命令行&#xff0c;得到版本号证明系统中已经安装node node -v //v18.17.0 2、使用npm 全局安装typeScript # 全局安装 TypeScript npm i -g typescript 二、检查是否安装成功ts #检查t…...

SWUST 派森练习题:P111. 摩斯密码翻译器

描述 摩斯密码&#xff08;morse code)&#xff0c;又称摩斯电码、摩尔斯电码&#xff08;莫尔斯电码&#xff09;&#xff0c;是一种时通时断的信号代码&#xff0c;通过不同的信号排列顺序来表达不同的英文字母、数字和标点符号&#xff1b;通信时&#xff0c;将英文字母等内…...

如何在控制台查看excel内容

背景 最近发现打开电脑的excel很慢&#xff0c;而且使用到的场景很少&#xff0c;也因为mac自带了预览的功能。但是shigen就是闲不住&#xff0c;想自己搞一个excel预览软件&#xff0c;于是在一番技术选型之后&#xff0c;我决定使用python在控制台显示excel的内容。 具体的需…...

Echarts、js编写“中国主要城市空气质量对比”散点图 【亲测】

本次实验通过可视化工具Echarts来对全国主要城市的&#xff30;&#xff2d;2.5的值进行直观的展示&#xff0c;使人们可以快速的发现信息的关键点&#xff0c;从而对各个城市的空气质量情况有直观的了解。 先看效果 上代码&#xff1a; <!DOCTYPE html> <html>&…...

linux不分区直接在文件系统根上开swap

root下&#xff0c;直接创swapfile dd if/dev/zero of/swapfile bs1M count8192然后 mkswap swapfile swapon swapfile修改fstab # /etc/fstab: static file system information. # # Use blkid to print the universally unique identifier for a # device; this may be us…...

React请求机制优化思路 | 京东云技术团队

说起数据加载的机制&#xff0c;有一个绕不开的话题就是前端性能&#xff0c;很多电商门户的首页其实都会做一些垂直的定制优化&#xff0c;比如让请求在页面最早加载&#xff0c;或者在前一个页面就进行预加载等等。随着react18的发布&#xff0c;请求机制这一块也是被不断谈起…...

CompletableFuture总结和实践

CompletableFuture被设计在Java中进行异步编程。异步编程意味着在主线程之外创建一个独立的线程&#xff0c;与主线程分隔开&#xff0c;并在上面运行一个非阻塞的任务&#xff0c;然后通知主线程进展&#xff0c;成功或者失败。 一、概述 1.CompletableFuture和Future的区别&…...

做坏事网站/百度入口官网

异步请求-AjaxAjax基本介绍Ajax基本应用场景Ajax原理示意图Ajax使用Ajax应用应用升级-接入数据库JQuery操作Ajax原生Ajax请求问题分折$.ajax 介绍$.get 与 $.post 介绍getJson 介绍Jquery $.ajax 应用案例Jquery $.get 应用案例Jquery $.post 应用案例Jquery getJson 应用案例A…...

好看动漫网替代网站/在百度怎么发广告做宣传

idea服务器与项目连接数据库 内容精选换一换Windows操作系统自带ODBC数据源管理器&#xff0c;无需用户手动安装管理器便可直接进行配置。将GaussDB-8.1.1-Windows-Odbc.tar.gz解压后&#xff0c;根据需要&#xff0c;点击psqlodbc.msi(32位)或者psqlodbc_x64.msi(64 位)进行驱…...

西安做网站哪家公司好/深圳新闻今日最新

1.个人隐私问题 个人隐私包括传统的个人隐私和现代个人数据。传统的个人隐私有姓名&#xff0c;出生年月&#xff0c;身份证编号&#xff0c;婚姻家庭&#xff0c;教育等。现代个人数据有用户名和密码&#xff0c;IP地址等。合理合法的隐私应受到保护。在计算机时代&#xff0c…...

卫龙的网站做的污污分/it培训班出来工作有人要么

无论是大龄儿童&#xff0c;还是带娃的老母亲每次在宜家的儿童区带着嫌弃又难以抗拒的心情选了又选最终开开心心带走一个“丑娃娃”&#xff08;口嫌体正直&#xff01;&#xff09;emmm&#xff0c;如果这还不算什么接着看&#xff01;掉威亚的大象&#xff08;怎么想的&#…...

做企业网站设计/自己做网站需要多少钱

keys命令的用法&#xff1a; keys pattern 查找符合正则匹配的key的列表。扫描对象是Redis服务中所有的key&#xff0c;想想都很慢对不对&#xff1f; 同时执行keys命令的同时&#xff0c;Redis进程将被阻塞&#xff0c;无法执行其他命令&#xff0c;假如超过了哨兵的down-af…...

企业网关官网/如何提高网站seo排名

最近「打工人」这个词火了那么问题来了你知道“打工人”用英语怎么说吗&#xff1f;“hit workers”&#xff1f;&#xff1f;&#xff1f;不对哦&#xff01;接下来就让我们看看“打工人”有哪些英语表达吧&#xff01;01 migrant workers“打工”最初的含义就是“外出打工人员…...