Jetpack DataStore

文章目录

  • Jetpack DataStore
    • 概述
    • DataStore 对比 SP
    • 添加依赖库
    • Preferences DataStore
      • 路径
      • 创建 Preferences DataStore
      • 获取数据
      • 保存数据
      • 修改数据
      • 删除数据
      • 清除全部数据
    • Proto DataStore
      • 配置
        • AndroidStudio安装插件
        • 配置proto文件
        • 创建序列化器
      • 创建 Proto DataStore
      • 获取数据
      • 保存数据
      • 修改数据
      • 删除Map数据
      • 清除数据
    • 代码下载

Jetpack DataStore

概述

Jetpack DataStore 是一种数据存储解决方案,允许您使用协议缓冲区存储键值对或类型化对象。DataStore 使用 Kotlin 协程和 Flow 以异步、一致的事务方式存储数据。

DataStore 提供两种不同的实现:Preferences DataStore 和 Proto DataStore。

  • Preferences DataStore 使用键存储和访问数据。此实现不需要预定义的架构,也不确保类型安全。
  • Proto DataStore 将数据作为自定义数据类型的实例进行存储。此实现要求您使用协议缓冲区来定义架构,但可以确保类型安全。

DataStore 官方文档

Proto3 语法入门

Proto3 官方语法指南

DataStore 对比 SP

SharedPreference(简称SP) 是一个轻量级的数据存储方式,使用方便,以键值对的形式存储在本地。

SP的缺点:

  • SP不能保证类型安全。如果存的数据和取的数据的类型不一致时会报异常。
  • SP加载的数据会一直停留在内存中。
  • 不支持多进程。
  • 读写性能差,可能阻塞UI线程,可能引起ANR。

DataStore优点:

  • 读写性能高。基于协程和Flow保证了UI线程的安全性。
  • 从一定程度上保证类型安全。

添加依赖库

project/build.gradle

buildscript {   
    dependencies {
        // Proto DataStore
        classpath 'com.google.protobuf:protobuf-gradle-plugin:0.8.19'
    }
}

module/build.gradle

plugins {
    id 'com.android.application'
    id 'kotlin-android'
    id 'com.google.protobuf'
}

dependencies {
    // Preferences DataStore
    implementation "androidx.datastore:datastore-preferences:1.0.0"
    implementation "androidx.datastore:datastore-core:1.0.0"

    // Proto DataStore
    implementation 'androidx.datastore:datastore-core:1.0.0'
    implementation 'com.google.protobuf:protobuf-javalite:3.10.0'

    implementation "androidx.lifecycle:lifecycle-runtime-ktx:2.5.0"

}


protobuf {
    protoc {
        artifact = "com.google.protobuf:protoc:3.14.0"
    }

    // 为该项目中的 Protobufs 生成 java Protobuf-lite 代码。
    generateProtoTasks {
        all().each { task ->
            task.builtins {
                java {
                    option 'lite'
                }
            }
        }
    }
}

Preferences DataStore

路径

DataStore 生成的缓存文件存放在 /data/data/<包名>/files/datastore 目录下:

在这里插入图片描述

创建 Preferences DataStore

val Context.dataStore: DataStore<Preferences> by preferencesDataStore(name = "user_info")

获取数据

lifecycleScope.launch {
    dataStore.edit { preferences ->
        // 先通过 stringPreferencesKey() 方法获取指定Key
        val nameKey = stringPreferencesKey("name")
        val ageKey = intPreferencesKey("age")
        val sexKey = booleanPreferencesKey("sex")
        // 通过Key获取值
        val name = preferences[nameKey]
        val age = preferences[ageKey]
        val sex = preferences[sexKey]
        logE("name:$name age:$age sex:$sex")
    }
}

保存数据

dataStore.edit { preferences ->
    preferences[stringPreferencesKey("name")] = "小明"
    preferences[intPreferencesKey("age")] = 18
    preferences[booleanPreferencesKey("sex")] = true
}

修改数据

 dataStore.edit { preferences ->
     preferences[stringPreferencesKey("name")] = "小黑"
     preferences[intPreferencesKey("age")] = 28
     preferences[booleanPreferencesKey("sex")] = false
 }

删除数据

dataStore.edit { preferences ->
    val removeValue = preferences.remove(stringPreferencesKey("name"))
    logE("remove:$removeValue")
}

清除全部数据

dataStore.edit { preferences ->
    preferences.clear()
}

Proto DataStore

配置

AndroidStudio安装插件

在这里插入图片描述

配置proto文件

先新建 proto 目录:

在这里插入图片描述

再创建 person.proto 文件,并写入:

syntax = "proto3";

option java_package = "com.example.datastoredemo"; //设置生成的类所在的包
option java_multiple_files = true; //可能会有多个文件。

message PersonPreferences {
  string name = 1; //String类型
  int32 age = 2; //int类型
  bool sex = 3; //boolean类型
  repeated string address = 4; //String[]数组
  map<string, string> fruits = 5; //Map类型
}
创建序列化器
object PersonSerializer : Serializer<PersonPreferences> {
    override val defaultValue: PersonPreferences
        get() = PersonPreferences.getDefaultInstance()

    override suspend fun writeTo(t: PersonPreferences, output: OutputStream) {
        t.writeTo(output)
    }

    override suspend fun readFrom(input: InputStream): PersonPreferences {
        try {
            return PersonPreferences.parseFrom(input)
        } catch (exception: InvalidProtocolBufferException) {
            throw CorruptionException("Cannot read proto.", exception)
        }
    }
}

创建 Proto DataStore

val Context.personDataStore: DataStore<PersonPreferences> by dataStore(
    fileName = "person.pb", serializer = PersonSerializer
)

获取数据

lifecycleScope.launch {
    personDataStore.data.first().let { preferences ->
        val name = preferences.name
        val age = preferences.age
        val sex = preferences.sex
        val address = preferences.addressList
        val fruits = preferences.fruitsMap
        logE("name:$name age:$age sex:$sex address:$address fruits:$fruits")
    }
}

保存数据

preferences.toBuilder()
    .setName("小白")
    .setAge(28)
    .setSex(true)
    .addAddress("广东省")
    .addAddress("广州市")
    .addAddress("黄埔区")
    .putFruits("apple", "苹果")
    .putFruits("banner", "香蕉")
    .putFruits("cherry", "樱桃")
    .build()
preferences.toBuilder()
    .setName("小白")
    .setAge(28)
    .setSex(true)
    .addAllAddress(listOf("广东省", "广州市", "黄埔区"))
    .putAllFruits(mapOf("apple" to "苹果", "banner" to "香蕉", "cherry" to "樱桃"))
    .build()

修改数据

personDataStore.updateData { preferences -
    preferences.toBuilder()
        .setName("小黑")
        .setAge(38)
        .setSex(false)
        .setAddress(0, "湖南省")
        .setAddress(1, "长沙市")
        .setAddress(2, "芙蓉区")
        .putFruits("apple", "苹果1号")
        .build()
}

删除Map数据

 personDataStore.updateData { preferences ->
     preferences.toBuilder()
         .removeFruits("apple")  // 删除map数据
         .build()
 }

清除数据

personDataStore.updateData { preferences ->
    // 清除所有数据
    preferences.toBuilder()
        .clear()
        .build()
    // 依次清除数据
      preferences.toBuilder()
          .clearName()
          .clearAge()
          .clearSex()
          .clearAddress()
          .clearFruits()
          .build()
}
personDataStore.updateData { preferences ->
    // 清除所有数据
    preferences.toBuilder()
        .clear()
        .build()
    // 依次清除数据
      preferences.toBuilder()
          .clearName()
          .clearAge()
          .clearSex()
          .clearAddress()
          .clearFruits()
          .build()
}

代码下载

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/263093.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Spring AOP入门指南:轻松掌握面向切面编程的基础知识

面向切面编程 1&#xff0c;AOP简介1.1 什么是AOP?1.2 AOP作用1.3 AOP核心概念 2&#xff0c;AOP入门案例2.1 需求分析2.2 思路分析2.3 环境准备2.4 AOP实现步骤步骤1:添加依赖步骤2:定义接口与实现类步骤3:定义通知类和通知步骤4:定义切入点步骤5:制作切面步骤6:将通知类配给…

swing快速入门(二十三)弹球小游戏

注释很详细&#xff0c;直接上代码 上一篇 新增内容 1. 键盘响应监听 2. 使用定时器事件更新画板 3. 定时器事件的开始与暂停 4. 弹球小游戏的坐标逻辑判断 import javax.swing.*; import java.awt.*; import java.awt.event.*;public class swing_test_19 {//创建一个窗…

如何选择适合的UI自动化测试工具

随着软件开发项目的复杂性增加&#xff0c;UI自动化测试成为确保应用程序质量的关键步骤之一。然而&#xff0c;在选择UI自动化测试工具时&#xff0c;开发团队需要考虑多个因素&#xff0c;以确保选取的工具适用于项目需求并提供可靠的测试结果。 1. 了解项目需求 在选择UI自动…

esp32-s3训练自己的数据进行目标检测、图像分类

esp32-s3训练自己的数据进行目标检测、图像分类 一、下载项目二、环境三、训练和导出模型四、部署模型五、存在的问题 esp-idf的安装参考我前面的文章&#xff1a; esp32cam和esp32-s3烧录human_face_detect实现人脸识别 一、下载项目 训练、转换模型&#xff1a;ModelAssist…

大型医院PACS系统源码,影像存储与传输系统源码,支持多种图像处理及三维重建功能

PACS系统是医院影像科室中应用的一种系统&#xff0c;主要用于获取、传输、存档和处理医学影像。它通过各种接口&#xff0c;如模拟、DICOM和网络&#xff0c;以数字化的方式将各种医学影像&#xff0c;如核磁共振、CT扫描、超声波等保存起来&#xff0c;并在需要时能够快速调取…

Docker部署 flowable-ui 进行流程建模

Docker部署 flowable-ui 进行流程建模 简介 安装Docker Desktop,本篇无安装步骤安装正常打开运行后&#xff0c;正式开始部署flowable-uicmd执行拉取镜像操作docker pull flowable/flowable-uicmd启动镜像docker run -d --name flowable -p 8081:8080 flowable/flowable-ui修…

基于博弈树的开源五子棋AI教程[4 静态棋盘评估]

引子 静态棋盘的评估是棋力的一个很重要的体现&#xff0c;一个优秀的基于博弈树搜索的AI往往有上千行工作量&#xff0c;本文没有做深入讨论&#xff0c;仅仅写了个引子用来抛砖引玉。 评估一般从两个角度入手&#xff0c;一个是子力&#xff0c;另一个是局势。 1 评估维度 …

SSH无密登陆配置

1 SSH介绍 ssh命令用于远程登录到其他计算机&#xff0c;实现安全的远程管理。 基本语法&#xff1a; ssh 域名/IP地址 示例&#xff1a; &#xff08;1&#xff09;从hadoop100服务器上远程连接hadoop101服务器 [hadoophadoop100 ~]$ ssh hadoop101 如果出现如下内容 Ar…

【C语言】动态内存管理基础知识——动态通讯录,如何实现通讯录容量的动态化

引言 动态内存管理的函数有&#xff1a;malloc,calloc,ralloc,free,本文讲解动态内存函数和使用&#xff0c;如何进行动态内存管理,实现通讯录联系人容量的动态化&#xff0c;对常见动态内存错误进行总结。 ✨ 猪巴戒&#xff1a;个人主页✨ 所属专栏&#xff1a;《C语言进阶》…

idea 远程调试linux上的代码

背景介绍 开发过程中&#xff0c;我们经常会遇到部署的代码运行出问题、看日志由不是很直观、我们希望可以像调试本地代码一样去调试远程代码; IDEA提供了Remote工具,基于JVM的跨平台能力&#xff0c;我们可以远程调试部署的代码。 前提 保证远程和本地跑的代码是一致的 操…

yocto系列讲解[实战篇]93 - 添加Qtwebengine和Browser实例

By: fulinux E-mail: fulinux@sina.com Blog: https://blog.csdn.net/fulinus 喜欢的盆友欢迎点赞和订阅! 你的喜欢就是我写作的动力! 目录 概述集成meta-qt5移植过程中的问题问题1:virtual/libgl set to mesa, not mesa-gl问题2:dmabuf-server-buffer tries to use undecl…

GBASE南大通用数据库在Windows和Linux中创建数据源

Windows 中数据源信息可能存在于两个地方&#xff1a;在 Windows 注册表中&#xff08;对 Windows 系统&#xff09;&#xff0c; 或在一个 DSN 文件中&#xff08;对任何系统&#xff09;。 如果信息在 Windows 注册表中&#xff0c;它叫做“机器数据源”。它可能是一个“用 …

Sentinel 流量治理组件教程

前言 官网首页&#xff1a;home | Sentinel (sentinelguard.io) 随着微服务的流行&#xff0c;服务和服务之间的稳定性变得越来越重要。Sentinel 是面向分布式、多语言异构化服务架构的流量治理组件&#xff0c;主要以流量为切入点&#xff0c;从流量路由、流量控制、流量整形…

京东tp26旋转验证

记录一下&#xff0c;狗东的tp26旋转验证码&#xff0c;难点还是在这个轨迹上。我真的是一点都不喜欢玩轨迹&#xff01;&#xff01;&#xff01;&#xff01; 类似于百度旋转的图&#xff0c;不过他这个东西还是稍微有点差距的。 鉴于生病了脑子不太好使&#xff0c;就不过多…

全光谱全天候耐久性性能测试氙灯老化箱太阳光模拟器

氙灯老化箱应用领域 添加剂 & 着色剂胶粘剂 & 密封剂建材汽车食品& 饮料平面艺术 包装材料油漆& 涂料光伏塑料纺织品风能 & 太阳能消费类电子产品 氙灯老化箱描述 氙灯老化箱是一种用于模拟阳光、雨水和温度循环的老化测试设备。它使用氙灯作为光源&am…

移动SEO:如何针对任何设备优化您的网站

您快速进行 Google 搜索并阅读一堆结果。然后&#xff0c;您会发现一些网站具有您正在寻找的答案。 但是你从SERP中选择的第一个&#xff0c;也是最有前途的网站&#xff0c;在你最喜欢的移动设备上无法正常工作。 所以&#xff0c;你关闭它&#xff0c;看看下一个网站是否有…

Ansible自动化工具之Playbook剧本编写

目录 Playbook的组成部分 实例模版 切换用户 指定声明用户 声明和引用变量&#xff0c;以及外部传参变量 playbook的条件判断 ​编辑 习题 ​编辑 ansible-playbook的循环 item的循环 ​编辑 list循环 ​编辑 together的循环&#xff08;列表对应的列&#xff0…

初识Docker-什么是docker

Docker是一个快速交付应用、运行应用的技术 目录 一、Docker 二、运用场景 一、什么是Docker&#xff1f;它的作用是什么&#xff1f; Docker如何解决大型项目依赖关系复杂&#xff0c;不同组件依赖的兼容性问题? Docker允许开发中将应用、依赖、函数库、配置一起打包&…

专业数据中台哪个好?亿发数字化运营平台解决方案,助力大中型企业腾飞

数据中台的核心在于避免数据的重复计算&#xff0c;通过数据服务化的方式提升数据的共享能力&#xff0c;为数据应用赋能。 在信息技术时代&#xff0c;企业的信息系统建设通常是由各个组织和功能单元独立完成&#xff0c;以满足各自的需求。这导致了“数据孤岛”和“数据烟囱”…

华为端口隔离简单使用方法同vlan下控制个别电脑不给互通

必须得用access接口&#xff0c;hybrid口不行 dhcp enable interface Vlanif1 ip address 192.168.1.1 255.255.255.0 dhcp select interface interface MEth0/0/1 interface GigabitEthernet0/0/1 port link-type access port-isolate enable group 1 interface GigabitEther…