转载请标明出处:http://blog.csdn.net/zhaoyanjun6/article/details/127358235
本文出自【赵彦军的博客】

文章目录

  • 概述
  • 使用
  • DataStore 本地数据
  • 查看DataStore 文件
  • Key 的枚举
  • 同步API
  • 清除内容
  • 包含key
  • SharedPreferences 数据迁移
  • DataStore 源码

概述

官方文档:https://developer.android.com/topic/libraries/architecture/datastore

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

使用

添加依赖:

implementation "androidx.datastore:datastore-preferences:1.0.0"

定义dataStore

//定义DataStore
val Context.dataStore: DataStore<Preferences> by preferencesDataStore(name = "user_info")//定义key
val keyName = stringPreferencesKey("name")
val keyAge = intPreferencesKey("age")

保存数据:

import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.datastore.preferences.core.edit
import androidx.lifecycle.lifecycleScope
import kotlinx.coroutines.launchclass MainActivity : AppCompatActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)lifecycleScope.launch {saveData("zhaoyanjun", 18)}}//dataStore保存数据suspend fun saveData(name: String, age: Int) {dataStore.edit {it[keyName] = name //保存字符串it[keyAge] = age //保存int}}}

获取数据

class MainActivity : AppCompatActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)lifecycleScope.launch {getData()}}//dataStore获取数据,collect 是一个挂起函数,所以会一直挂起,只要name的值发起变更,collect 就会回调suspend fun getData() {val nameFlow = dataStore.data.map {it[keyName]}nameFlow.collect { name ->Log.d("getData ", "name $name")}}
}

dataStore.data 是一个 Flow 对象,使用一个 collect 操作符 可以接受 值的变化,一旦值发生变化,collect { } 就会回调,可以实现数据驱动 UI 的效果。

DataStore 本地数据

DataStore 文件在 files/datastore/ 目录,完整路径是

/data/data/com.zyj.exoplayerdemo/files/datastore/user_info.preferences_pb

查看DataStore 文件

双击 user_info.preferences_pb 在 AS 里打开

发现是乱码。

点击右键把 user_info.preferences_pb 导出到桌面


在 mac appStore 下载安装 Protobuf Viewer

Protobuf Viewer 打开我们导出的 pb 文件

Key 的枚举

在文中我们用到了

stringPreferencesKey("name")
intPreferencesKey("age")

除此之外,DataStore 还提供了其他类型的 Key

@JvmName("intKey")
public fun intPreferencesKey(name: String): Preferences.Key<Int> = Preferences.Key(name)@JvmName("doubleKey")
public fun doublePreferencesKey(name: String): Preferences.Key<Double> = Preferences.Key(name)@JvmName("stringKey")
public fun stringPreferencesKey(name: String): Preferences.Key<String> = Preferences.Key(name)@JvmName("booleanKey")
public fun booleanPreferencesKey(name: String): Preferences.Key<Boolean> = Preferences.Key(name)@JvmName("floatKey")
public fun floatPreferencesKey(name: String): Preferences.Key<Float> = Preferences.Key(name)@JvmName("longKey")
public fun longPreferencesKey(name: String): Preferences.Key<Long> = Preferences.Key(name)@JvmName("stringSetKey")
public fun stringSetPreferencesKey(name: String): Preferences.Key<Set<String>> =Preferences.Key(name)

同步API

在上面的演示过程中,我们使用 Flowcollect { } 操作符 , 但是 collect { } 会一直处于挂起状态,只要值发生变化,我们就会收到通知,符合数据驱动 UI 的设计模式。

但是在现实开发中,我们往往需要一个同步 api , 仅仅获取当前一次值,我们只关注本次的值是什么,至于以后得值变化,我们不关心。DataStore 提供了 同步api 来供我们使用 。

override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)lifecycleScope.launch {//同步apival first = dataStore.data.first()val name = first[keyName]val age = first[keyAge]Log.d("getData ", "name $name")Log.d("getData ", "age $age")}}

如果是 pb 文件里面没有值,那么就会返回 null

com.zyj.exoplayerdemo D/getData: name null
com.zyj.exoplayerdemo D/getData: age null

所以我们可以把获取名字,封装成一个同步方法

suspend fun getNameData(): String? {val nameFlow = dataStore.data.map {it[keyName]}return nameFlow.first()
}

清除内容

清除某个key

val keyName = stringPreferencesKey("name")suspend fun clear() {dataStore.edit {it.remove(keyName)}
}

清除所有值

   suspend fun clear() {dataStore.edit {it.clear()}}

包含key

suspend fun contains() {dataStore.edit {//是否包含某个keyvar result =  it.contains(keyName)}
}

SharedPreferences 数据迁移

如果你原来是用 SharedPreferences , 想换到 DataStore 上,DataStore 提供了一键迁移,就一行代码就搞定了。

val Context.dataStore: DataStore<Preferences> by preferencesDataStore(name = "user_info",produceMigrations = { context ->listOf(SharedPreferencesMigration(context, "sp_file_name"))})

DataStore 源码

DataStore 是一个接口

public interface DataStore<T> {/*** Provides efficient, cached (when possible) access to the latest durably persisted state.* The flow will always either emit a value or throw an exception encountered when attempting* to read from disk. If an exception is encountered, collecting again will attempt to read the* data again.** Do not layer a cache on top of this API: it will be be impossible to guarantee consistency.* Instead, use data.first() to access a single snapshot.** @return a flow representing the current state of the data* @throws IOException when an exception is encountered when reading data*/public val data: Flow<T>/*** Updates the data transactionally in an atomic read-modify-write operation. All operations* are serialized, and the transform itself is a coroutine so it can perform heavy work* such as RPCs.** The coroutine completes when the data has been persisted durably to disk (after which* [data] will reflect the update). If the transform or write to disk fails, the* transaction is aborted and an exception is thrown.** @return the snapshot returned by the transform* @throws IOException when an exception is encountered when writing data to disk* @throws Exception when thrown by the transform function*/public suspend fun updateData(transform: suspend (t: T) -> T): T
}

Android DataStore 使用详解相关推荐

  1. 《Android游戏开发详解》——第1章,第1.6节函数(在Java中称为“方法”更好)...

    本节书摘来自异步社区<Android游戏开发详解>一书中的第1章,第1.6节函数(在Java中称为"方法"更好),作者 [美]Jonathan S. Harbour,更 ...

  2. JMessage Android 端开发详解

    JMessage Android 端开发详解 目前越来越多的应用会需要集成即时通讯功能,这里就为大家详细讲一下如何通过集成 JMessage 来为你的 App 增加即时通讯功能. 首先,一个最基础的 ...

  3. 《Java和Android开发实战详解》——2.5节良好的Java程序代码编写风格

    本节书摘来自异步社区<Java和Android开发实战详解>一书中的第2章,第2.5节良好的Java程序代码编写风格,作者 陈会安,更多章节内容可以访问云栖社区"异步社区&quo ...

  4. Android事件流程详解

    Android事件流程详解 网络上有不少博客讲述了android的事件分发机制和处理流程机制,但是看过千遍,总还是觉得有些迷迷糊糊,因此特地抽出一天事件来亲测下,向像我一样的广大入门程序员详细讲述an ...

  5. Android Studio 插件开发详解二:工具类

    转载请标明出处:http://blog.csdn.net/zhaoyanjun6/article/details/78112856 本文出自[赵彦军的博客] 在插件开发过程中,我们按照开发一个正式的项 ...

  6. 《Android游戏开发详解》一2.16 区分类和对象

    本节书摘来异步社区<Android游戏开发详解>一书中的第2章,第2.16节,作者: [美]Jonathan S. Harbour 译者: 李强 责编: 陈冀康,更多章节内容可以访问云栖社 ...

  7. Android Framework系统服务详解

    Android Framework系统服务详解 操作环境 系统:Linux (Ubuntu 12.04) 平台:高通 Android版本:5.1 PS: 符号...为省略N条代码 一.大致原理分析 A ...

  8. android屏幕适配详解

    android屏幕适配详解 官方地址:http://developer.android.com/guide/practices/screens_support.html 一.关于布局适配建议 1.不要 ...

  9. Android LiveData组件详解以及LiveDataBus

    转载请标明出处:https://blog.csdn.net/zhaoyanjun6/article/details/99749323 本文出自[赵彦军的博客] 一.LiveData简介 LiveDat ...

  10. Android Studio 插件开发详解四:填坑

    转载请标明出处:http://blog.csdn.net/zhaoyanjun6/article/details/78265540 本文出自[赵彦军的博客] 系列目录 Android Gradle使用 ...

最新文章

  1. php手机电脑,php用手机关计算机(电脑)
  2. python画仿真图-Python数据分析:绘图可视化之matplotlib入门
  3. 20190429 照片里面的GPS信息确实会暴露经纬度
  4. clang 搭建和编译boost 和zero ICE库 (Ubuntu10 64)
  5. 【报告分享】百度大脑AI技术成果白皮书2018-2019.pdf
  6. [Python] L1-026. I Love GPLT-PAT团体程序设计天梯赛GPLT
  7. vue表单实现输入框控制输入小数点后两位
  8. 《结构方程模型及其应用》学习笔记0504第一、二章
  9. 安装树莓派摄像头模块方法
  10. 函数数列极限求法总结
  11. 各省生活资料PPI数据(2009-2018年)
  12. matlab 生命游戏
  13. Linux的web视频服务器的构建 (chinaitlab)
  14. 计算机如何通过手机连接网络打印机,手机连接电脑打印机怎么设置
  15. 轮廓图(Silhouette)
  16. Easyui数据表格合并单元格
  17. 国徽FLASH SM25QH256M烧录问题总结
  18. 【Database】数据库常见面试题【转】
  19. 电动汽车智能充电桩的设计分析
  20. spidermonkey php,javascript SpiderMonkey中的函数序列化如何进行_基础知识

热门文章

  1. python 安全编码代码审计
  2. win7下的HP1010打印机驱动安装
  3. 颜色值不透明度对应表(0%-100%)
  4. 群晖 android软件,群晖-手机端常用App
  5. linux 中cat用法
  6. 区块链在版权保护方面的探索与实践
  7. 基于Basys3设计的FPGA多功能电子琴
  8. 云原生转换过程中常见的偏见和推动
  9. 前端请求接口出现415错误
  10. Python Sorted Containers