当前位置: 首页 > 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的连接方…...

云计算——弹性云计算器(ECS)

弹性云服务器&#xff1a;ECS 概述 云计算重构了ICT系统&#xff0c;云计算平台厂商推出使得厂家能够主要关注应用管理而非平台管理的云平台&#xff0c;包含如下主要概念。 ECS&#xff08;Elastic Cloud Server&#xff09;&#xff1a;即弹性云服务器&#xff0c;是云计算…...

基于uniapp+WebSocket实现聊天对话、消息监听、消息推送、聊天室等功能,多端兼容

基于 ​UniApp + WebSocket​实现多端兼容的实时通讯系统,涵盖WebSocket连接建立、消息收发机制、多端兼容性配置、消息实时监听等功能,适配​微信小程序、H5、Android、iOS等终端 目录 技术选型分析WebSocket协议优势UniApp跨平台特性WebSocket 基础实现连接管理消息收发连接…...

高频面试之3Zookeeper

高频面试之3Zookeeper 文章目录 高频面试之3Zookeeper3.1 常用命令3.2 选举机制3.3 Zookeeper符合法则中哪两个&#xff1f;3.4 Zookeeper脑裂3.5 Zookeeper用来干嘛了 3.1 常用命令 ls、get、create、delete、deleteall3.2 选举机制 半数机制&#xff08;过半机制&#xff0…...

华为OD机试-食堂供餐-二分法

import java.util.Arrays; import java.util.Scanner;public class DemoTest3 {public static void main(String[] args) {Scanner in new Scanner(System.in);// 注意 hasNext 和 hasNextLine 的区别while (in.hasNextLine()) { // 注意 while 处理多个 caseint a in.nextIn…...

Psychopy音频的使用

Psychopy音频的使用 本文主要解决以下问题&#xff1a; 指定音频引擎与设备&#xff1b;播放音频文件 本文所使用的环境&#xff1a; Python3.10 numpy2.2.6 psychopy2025.1.1 psychtoolbox3.0.19.14 一、音频配置 Psychopy文档链接为Sound - for audio playback — Psy…...

Redis的发布订阅模式与专业的 MQ(如 Kafka, RabbitMQ)相比,优缺点是什么?适用于哪些场景?

Redis 的发布订阅&#xff08;Pub/Sub&#xff09;模式与专业的 MQ&#xff08;Message Queue&#xff09;如 Kafka、RabbitMQ 进行比较&#xff0c;核心的权衡点在于&#xff1a;简单与速度 vs. 可靠与功能。 下面我们详细展开对比。 Redis Pub/Sub 的核心特点 它是一个发后…...

三分算法与DeepSeek辅助证明是单峰函数

前置 单峰函数有唯一的最大值&#xff0c;最大值左侧的数值严格单调递增&#xff0c;最大值右侧的数值严格单调递减。 单谷函数有唯一的最小值&#xff0c;最小值左侧的数值严格单调递减&#xff0c;最小值右侧的数值严格单调递增。 三分的本质 三分和二分一样都是通过不断缩…...

【Android】Android 开发 ADB 常用指令

查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...

nnUNet V2修改网络——暴力替换网络为UNet++

更换前,要用nnUNet V2跑通所用数据集,证明nnUNet V2、数据集、运行环境等没有问题 阅读nnU-Net V2 的 U-Net结构,初步了解要修改的网络,知己知彼,修改起来才能游刃有余。 U-Net存在两个局限,一是网络的最佳深度因应用场景而异,这取决于任务的难度和可用于训练的标注数…...

认识CMake并使用CMake构建自己的第一个项目

1.CMake的作用和优势 跨平台支持&#xff1a;CMake支持多种操作系统和编译器&#xff0c;使用同一份构建配置可以在不同的环境中使用 简化配置&#xff1a;通过CMakeLists.txt文件&#xff0c;用户可以定义项目结构、依赖项、编译选项等&#xff0c;无需手动编写复杂的构建脚本…...