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

DataStore入门及在项目中的使用

首先给个官网的的地址:应用架构:数据层 - DataStore - Android 开发者  |  Android Developers

小伙伴们可以直接看官网的资料,本篇文章是对官网的部分细节进行补充

一、为什么要使用DataStore 代替SharedPreferences

SharedPreferences:

  • DataStore出现之前,我们用的最多的存储方式毫无疑问是SP,其使用方式简单、易用,广受好评。然而google对SP的定义为轻量级存储,如果存储的数据少,使用起来没有任何问题,当需要存储数据比较多时,SP可能会导致以下问题:
  • 1. SP第一次加载数据时需要全量加载,当数据量大时可能会阻塞UI线程造成卡顿;
  • 2. SP读写文件不是类型安全的,且没有发出错误信号的机制,缺少事务性API;
  • 3. commit() / apply()操作可能会造成ANR问题;
  • commit()是同步提交,会在UI主线程中直接执行IO操作,当写入操作耗时比较长时就会导致UI线程被阻塞,进而产生ANR;apply()虽然是异步提交,但异步写入磁盘时,如果执行了Activity / Service中的onStop()方法,那么一样会同步等待SP写入完毕,等待时间过长时也会引起ANR问题。

DataStore:

  • DataStore基于事务方式处理数据更新。

  • DataStore基于Kotlin Flow存取数据,默认在Dispatchers.IO里异步操作,避免阻塞UI线程,且在读取数据时能对发生的Exception进行处理。

  • 不提供apply()、commit()存留数据的方法。

  • 支持SP一次性自动迁移至DataStore中

总结:SharedPreferences卡进程,DataStore不卡进程

二、如何使用

  1. 添加依赖,在build.grade(:app)中添加:
    implementation("androidx.datastore:datastore-preferences:1.0.0")
    
  2. 创建 Preferences DataStore
    private val Context.mDataStore: DataStore<Preferences> by preferencesDataStore(name = "appData")
    private val mContext =MyApplication.mContext

    使用属性委托来创建,方便访问,并且可以保留为单例,只需要传入一个数据库名称即可,点开preferencesDataStore查看源码可以看到,只需要一个name参数,其他参数都是非必填,当初看到这个Context.mDataStore写法对新手有点蒙,各位小伙伴可以了解一下属性委托再看这个代码,preferencesDataStore返回的是PreferenceDataStoreSingletonDelegate,它的getValue方法如下,“委托必须提供一个操作符函数 getValue(),该函数具有以下参数:  thisRef —— 必须与 属性所有者 类型(对于扩展属性——指被扩展的类型)相同或者是其超类型。 property —— 必须是类型 KProperty<*> 或其超类型“。这样我们就知道为啥使用Context加扩展写法了,如果直接在Application这样有上下文Context的地方可以直接写mDataStore而不是Context.mDataStore

    override fun getValue(thisRef: Context, property: KProperty<*>): DataStore<Preferences>
  3. 使用相应的键类型函数为需要存储在 DataStore<Preferences> 实例中的每个值定义一个键。例如,如需为 int 值定义一个键,请使用 intPreferencesKey()。通常我们项目中需要存储类似userId,userName类似字段,我以它们两个举例说明:

    private val USER_ID = intPreferencesKey("userId")
    private val USER_NAME = stringPreferencesKey("userName")
  4. 存入数据:Preferences DataStore 提供了一个 edit() 函数,用于以事务方式更新 DataStore 中的数据。该函数的 transform 参数接受代码块,您可以在其中根据需要更新值。转换块中的所有代码均被视为单个事务。
        private suspend fun setUserName(userName: String) {mContext.mDataStore.edit { settings ->settings[USER_NAME] = userName}}private suspend fun setUserId(userId: Int) {mContext.mDataStore.edit { settings ->settings[USER_ID] = userId}}
  5. 读取数据:(我直接取Flow的第一个值)
    private suspend fun getUserId() {mUserId =  mDataStore.data.map { preferences ->preferences[USER_ID] ?: 0}.first()
    }private suspend fun getUserName() {mUserName = mDataStore.data.map { preferences ->preferences[USER_NAME] ?: "empty"}.first()
    }
  6. 如果是在Activity中可以直接使用lifecycleScope

    lifecycleScope.launch {getUserId()
    }
  7. 如果想在整个应用中随时调用,不跟随某个组件的生命周期,可以在Application中声明一个全局的协程作用域,注意释放

    override fun onCreate() {mApplicationScope = CoroutineScope(SupervisorJob() + Dispatchers.Main)mContext = applicationContext
    }companion object {var mContext: Context by Delegates.notNull()var mApplicationScope: CoroutineScope by Delegates.notNull()
    }override fun onLowMemory() {super.onLowMemory()mApplicationScope.cancel()
    }

    这样我们可以使用mApplicationScope随时存储和读取数据啦

  8. 我们不想读取和存储数据是异步操作,比如我们的网络请求一header里开始就需要userID和username判断用户是否登录,我们可以使用runBlocking阻塞进程

            runBlocking {//此处取Flow都是取第一个值,可以写两个取值操作,DataStoreUtil.getUserId()DataStoreUtil. getUserName()//如果是没有调用flow.first()方法,无法取到username,可以把取值放在不同协程中,Flow就不会相互干扰了
    //            launch {
    //                getUserId()
    //            }
    //            launch {
    //                getUserName()
    //            }}
    
  9. 附上代码地址:GitHub - scYao/DataStoreDmeo: DataStore Demo

相关文章:

DataStore入门及在项目中的使用

首先给个官网的的地址&#xff1a;应用架构&#xff1a;数据层 - DataStore - Android 开发者 | Android Developers 小伙伴们可以直接看官网的资料&#xff0c;本篇文章是对官网的部分细节进行补充 一、为什么要使用DataStore 代替SharedPreferences SharedPreferences&a…...

用Python爬取中国各省GDP数据

介绍 在数据分析和经济研究中&#xff0c;了解中国各省份的GDP数据是非常重要的。然而&#xff0c;手动收集这些数据可能是一项繁琐且费时的任务。幸运的是&#xff0c;Python提供了一些强大的工具和库&#xff0c;使我们能够自动化地从互联网上爬取数据。本文将介绍如何使用P…...

深度学习-第T5周——运动鞋品牌识别

深度学习-第T5周——运动鞋品牌识别 深度学习-第T5周——运动鞋品牌识别一、前言二、我的环境三、前期工作1、导入数据集2、查看图片数目3、查看数据 四、数据预处理1、 加载数据1、设置图片格式2、划分训练集3、划分验证集4、查看标签 2、数据可视化3、检查数据4、配置数据集 …...

自媒体的孔雀效应:插根鸡毛还是专业才华?

自媒体时代&#xff0c;让许多原本默默无闻的人找到了表达自己的平台。有人声称&#xff0c;现在这个时代&#xff0c;“随便什么人身上插根鸡毛就可以当孔雀了”。可是&#xff0c;事实真的如此吗&#xff1f; 首先&#xff0c;我们不能否认的是&#xff0c;自媒体确实为大众提…...

Linux系统优化

一、系统启动流程 1.centos6 centos6开机启动流程&#xff0c;传送门 2.centos7启动流程 二、系统启动运行级别 2.1 什么是运行级别 运行级别&#xff1a;指操作系统当前正在运行的功能级别&#xff1b; [rootweb01 ~]# ll /usr/lib/systemd/system lrwxrwxrwx. 1 root root…...

Java笔记_22(反射和动态代理)

Java笔记_22 一、反射1.1、反射的概述1.2、获取class对象的三种方式1.3、反射获取构造方法1.4、反射获取成员变量1.5、反射获取成员方法1.6、综合练习1.6.1、保存信息1.6.2、跟配置文件结合动态创建 一、反射 1.1、反射的概述 什么是反射? 反射允许对成员变量&#xff0c;成…...

前端web入门-HTML-day01

(创作不易&#xff0c;感谢有你&#xff0c;你的支持&#xff0c;就是我前行的最大动力&#xff0c;如果看完对你有帮助&#xff0c;请留下您的足迹&#xff09; 目录 HTML初体验 HTML 定义 标签语法 总结&#xff1a; HTML 基本骨架 基础知识&#xff1a; 总结&#…...

创建一个Go项目

创建一个Go项目 1.创建项目 package mainfunc main() {println("你好啊&#xff0c;简单点了&#xff01;") }如果是本地的话可以采用go run 项目名的方式。 可以采用go run --work 项目名的方式&#xff0c;此时可以展示日志信息。 如果是只编译的话 go build 项…...

从 Spring 的创建到 Bean 对象的存储、读取

目录 创建 Spring 项目&#xff1a; 1.创建一个 Maven 项目&#xff1a; 2.添加 Spring 框架支持&#xff1a; 3.配置资源文件&#xff1a; 4.添加启动类&#xff1a; Bean 对象的使用&#xff1a; 1.存储 Bean 对象&#xff1a; 1.1 创建 Bean&#xff1a; 1.2 存储 B…...

【一文吃透归并排序】基本归并·原地归并·自然归并 C++

目录 1 引入情境基本归并排序实现 C 2 原地归并排序2-1 死板的解法2-2 原地工作区2-3 链表归并排序 3 自底向上归并排序4 两路自然归并排序4-1 形式化描述4-2 代码实现 1 引入情境 归并思想&#xff1a;假设有两队小孩&#xff0c;都是从矮到高排序&#xff0c;现在通过一扇门后…...

读《Spring Boot 3核心技术与最佳实践》有感

我是谁&#xff1f; &#x1f468;‍&#x1f393;作者&#xff1a;bug菌 ✏️博客&#xff1a;CSDN、掘金、infoQ、51CTO等 &#x1f389;简介&#xff1a;CSDN/阿里云/华为云/51CTO博客专家&#xff0c;C站历届博客之星Top50&#xff0c;掘金/InfoQ/51CTO等社区优质创作者&am…...

板子短路了?

有段时间没更新了&#xff0c;主要是最近有点忙&#xff0c;当然也因为有点“懒”。 做这行业的都知道&#xff0c;下半年都是比较忙的&#xff0c;相信大家也是&#xff01; 相信做硬件的小伙伴们&#xff0c;遇到过短路的板子已经不计其数了。 短路带来的危害&#xff1a;…...

一行代码绘制高分SCI限制立方图

一、概述 Restricted cubic splines (RCS)是一种基于样条函数的非参数化模型&#xff0c;它可以可靠地拟合非线性关系&#xff0c;可以自适应地调整分割结点。在统计学和机器学习领域&#xff0c;RCS通常用来对连续型自变量进行建模&#xff0c;并在解释自变量与响应变量的关系…...

spring 容器结构/机制debug分析--Spring 学习的核心内容和几个重要概念--IOC 的开发模式--综合解图

目录 Spring Spring 学习的核心内容 解读上图: Spring 几个重要概念 ● 传统的开发模式 解读上图 ● IOC 的开发模式 解读上图 代码示例—入门 xml代码 注意事项和细节 1、说明 2、解释一下类加载路径 3、debug 看看 spring 容器结构/机制 综合解图 Spring Spr…...

excel实战小测第四

【项目背景】 本项目为某招聘网站部分招聘信息&#xff0c;要求对“数据分析师”岗位进行招聘需求分析&#xff0c;通过对城市、行业、学历要求、薪资待遇等不同方向进行相关性分析&#xff0c;加深对数据分析行业的了解。 结合企业真实招聘信息&#xff0c;可以帮助有意转向数…...

什么是SpringBoot自动配置

概述&#xff1a; 现在的Java面试基本都会问到你知道什么是Springboot的自动配置。为什么面试官要问这样的问题&#xff0c;主要是在于看你有没有对Springboot的原理有没有深入的了解&#xff0c;有没有看过Springboot的源码&#xff0c;这是区别普通程序员与高级程序员最好的…...

基于IC5000烧录器使用winIDEA烧写+调试程序(S32K324的软件烧写与调试)

目录 一、iSYSTEM简介二、如何使用iSYSTEM winIDEA烧写调试程序2.1 打开winIDEA&#xff1a;2.2 新建一个Workspace;2.3 硬件配置:2.4 选择CPU芯片型号&#xff1a;2.5 加载烧写文件&#xff1a;2.6 开始烧录程序&#xff1a;2.7 程序调试Debug&#xff1a;2.7.1 运行程序&…...

新手开始学【网络安全】要怎么入门?

前言&#xff1a;网络安全如何从零开始学习&#xff0c;少走弯路&#xff1f; 目录&#xff1a; 一&#xff0c;怎么入门&#xff1f; 1、Web 安全相关概念&#xff08;2 周&#xff09;2、熟悉渗透相关工具&#xff08;3 周&#xff09;3、渗透实战操作&#xff08;5 周&…...

Linux指令 快捷键

热键 上一次我们说到了linux的基本指令&#xff0c;这次我们先说一下热键 TAB TAB键在linux中有什么作用呢&#xff1f;&#xff1f; 在Linux中&#xff0c;假设我们想要输入的指令忘记了&#xff0c;我们可以TAB两下&#xff0c;帮我们补全命令或者假如命令太多&#xff0…...

Testing and fault tolerence考试要点

文章目录 ATPGFault modelScanFunctional testMemory BISTLogic BISTboundary scanATEIddq testingFault tolerant designRisk analysis ATPG ATPG工作流程fault collapsing的原则 Fault model 有哪些fault model以及他们的工作原理 Scan Scan寄存器结构Scan Chain的连接方…...

测试微信模版消息推送

进入“开发接口管理”--“公众平台测试账号”&#xff0c;无需申请公众账号、可在测试账号中体验并测试微信公众平台所有高级接口。 获取access_token: 自定义模版消息&#xff1a; 关注测试号&#xff1a;扫二维码关注测试号。 发送模版消息&#xff1a; import requests da…...

MPNet:旋转机械轻量化故障诊断模型详解python代码复现

目录 一、问题背景与挑战 二、MPNet核心架构 2.1 多分支特征融合模块(MBFM) 2.2 残差注意力金字塔模块(RAPM) 2.2.1 空间金字塔注意力(SPA) 2.2.2 金字塔残差块(PRBlock) 2.3 分类器设计 三、关键技术突破 3.1 多尺度特征融合 3.2 轻量化设计策略 3.3 抗噪声…...

React 第五十五节 Router 中 useAsyncError的使用详解

前言 useAsyncError 是 React Router v6.4 引入的一个钩子&#xff0c;用于处理异步操作&#xff08;如数据加载&#xff09;中的错误。下面我将详细解释其用途并提供代码示例。 一、useAsyncError 用途 处理异步错误&#xff1a;捕获在 loader 或 action 中发生的异步错误替…...

C++实现分布式网络通信框架RPC(3)--rpc调用端

目录 一、前言 二、UserServiceRpc_Stub 三、 CallMethod方法的重写 头文件 实现 四、rpc调用端的调用 实现 五、 google::protobuf::RpcController *controller 头文件 实现 六、总结 一、前言 在前边的文章中&#xff0c;我们已经大致实现了rpc服务端的各项功能代…...

<6>-MySQL表的增删查改

目录 一&#xff0c;create&#xff08;创建表&#xff09; 二&#xff0c;retrieve&#xff08;查询表&#xff09; 1&#xff0c;select列 2&#xff0c;where条件 三&#xff0c;update&#xff08;更新表&#xff09; 四&#xff0c;delete&#xff08;删除表&#xf…...

VB.net复制Ntag213卡写入UID

本示例使用的发卡器&#xff1a;https://item.taobao.com/item.htm?ftt&id615391857885 一、读取旧Ntag卡的UID和数据 Private Sub Button15_Click(sender As Object, e As EventArgs) Handles Button15.Click轻松读卡技术支持:网站:Dim i, j As IntegerDim cardidhex, …...

Objective-C常用命名规范总结

【OC】常用命名规范总结 文章目录 【OC】常用命名规范总结1.类名&#xff08;Class Name)2.协议名&#xff08;Protocol Name)3.方法名&#xff08;Method Name)4.属性名&#xff08;Property Name&#xff09;5.局部变量/实例变量&#xff08;Local / Instance Variables&…...

Matlab | matlab常用命令总结

常用命令 一、 基础操作与环境二、 矩阵与数组操作(核心)三、 绘图与可视化四、 编程与控制流五、 符号计算 (Symbolic Math Toolbox)六、 文件与数据 I/O七、 常用函数类别重要提示这是一份 MATLAB 常用命令和功能的总结,涵盖了基础操作、矩阵运算、绘图、编程和文件处理等…...

【JavaWeb】Docker项目部署

引言 之前学习了Linux操作系统的常见命令&#xff0c;在Linux上安装软件&#xff0c;以及如何在Linux上部署一个单体项目&#xff0c;大多数同学都会有相同的感受&#xff0c;那就是麻烦。 核心体现在三点&#xff1a; 命令太多了&#xff0c;记不住 软件安装包名字复杂&…...

OPenCV CUDA模块图像处理-----对图像执行 均值漂移滤波(Mean Shift Filtering)函数meanShiftFiltering()

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 在 GPU 上对图像执行 均值漂移滤波&#xff08;Mean Shift Filtering&#xff09;&#xff0c;用于图像分割或平滑处理。 该函数将输入图像中的…...