1 添加依赖

2 在 main 文件夹下创建 .proto 文件

3 编写 Serializer

4 编写基础存储工具类

5 举例使用

** 5.1 创建 DataStore 存储工具子类

** 5.2 基本使用

6 混淆

1 添加依赖

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

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

implementation "com.google.protobuf:protobuf-java:3.15.0"

2 在 main 文件夹下创建 .proto文件

.proto

syntax = "proto3";

option java_package = "com.afra55.xxx.ds.event";

option java_multiple_files = true;

message MessageEvent {

int32 type = 1;

string message = 2;

}

根据不同的存储需求来实现不同的 proto 文件,然后进行编译, java_package 是生成文件的路径

protoc -I=$SRC_DIR --java_out=$DST_DIR $SRC_DIR/ds.proto

例如当在 proto 文件夹下:

protoc -I=. --java_out=../java ./ds.proto

许多标准的简单数据类型都可以作为字段类型,包括bool,int32,float,double,和string。

ds

3 编写 Serializer

object MessageEventSerializer :Serializer{

override val defaultValue: MessageEvent

get() = MessageEvent.getDefaultInstance()

override fun readFrom(input: InputStream): MessageEvent {

try {

return MessageEvent.parseFrom(input)

} catch (e: Exception) {

throw CorruptionException("Cannot read proto.", e)

}

}

override fun writeTo(t: MessageEvent, output: OutputStream) {

t.writeTo(output)

}

}

4 编写基础存储工具类

import androidx.datastore.core.DataStore

import androidx.datastore.createDataStore

import androidx.datastore.preferences.core.*

import androidx.datastore.preferences.createDataStore

import androidx.datastore.createDataStore

import com.afra55.thunderomadtestapplication.AppApplication

import com.afra55.thunderomadtestapplication.ds.event.MessageEvent

import com.afra55.thunderomadtestapplication.toJsonString

import com.afra55.thunderomadtestapplication.toObject

import kotlinx.coroutines.Dispatchers

import kotlinx.coroutines.flow.Flow

import kotlinx.coroutines.flow.first

import kotlinx.coroutines.flow.flowOn

import kotlinx.coroutines.flow.map

import kotlin.reflect.KClass

/**

* @author Afra55

* @date 2/18/21

* A smile is the best business card.

*

* 需要添加混淆:

-keepclassmembers class * extends androidx.datastore.preferences.protobuf.GeneratedMessageLite {

;

}

*/

open class DataStoreBase(name: String) {

val dataStore: DataStore? by lazy {

AppApplication.context?.createDataStore(name)

}

val messageEventDataStore: DataStore? by lazy {

AppApplication.context?.createDataStore(

fileName = name,

serializer = MessageEventSerializer

)

}

suspend fun getString(key: String, defaultValue:String? = null):String? {

return dataStore?.data?.map { preferences ->

preferences[stringPreferencesKey(key)] ?: defaultValue

}?.first()

}

suspend fun getInt(key: String, defaultValue:Int? = null): Int? {

return dataStore?.data?.map { preferences ->

preferences[intPreferencesKey(key)] ?: defaultValue

}?.first()

}

suspend fun getDouble(key: String, defaultValue:Double? = null): Double? {

return dataStore?.data?.map { preferences ->

preferences[doublePreferencesKey(key)] ?: defaultValue

}?.first()

}

suspend fun getBoolean(key: String, defaultValue:Boolean? = null): Boolean? {

return dataStore?.data?.map { preferences ->

preferences[booleanPreferencesKey(key)] ?: defaultValue

}?.first()

}

suspend fun getFloat(key: String, defaultValue:Float? = null): Float? {

return dataStore?.data?.map { preferences ->

preferences[floatPreferencesKey(key)] ?: defaultValue

}?.first()

}

suspend fun getLong(key: String, defaultValue:Long? = null): Long? {

return dataStore?.data?.map { preferences ->

preferences[longPreferencesKey(key)] ?: defaultValue

}?.first()

}

suspend fun getStringSet(key: String, defaultValue:Set? = null): Set? {

return dataStore?.data?.map { preferences ->

preferences[stringSetPreferencesKey(key)] ?: defaultValue

}?.first()

}

suspend fun getObject(key: String, clazz: Class, defaultValue:T? = null): T? {

return dataStore?.data?.map { preferences ->

val a = preferences[stringPreferencesKey(key)]

if (a != null) {

a.toObject(clazz) as T

} else {

defaultValue

}

}?.first()

}

suspend fun get(key: String, clazz: KClass, defaultValue: T? = null): T? {

val pKey = when (clazz) {

String::class -> {

stringPreferencesKey(key)

}

Int::class -> {

intPreferencesKey(key)

}

Double::class -> {

doublePreferencesKey(key)

}

Boolean::class -> {

booleanPreferencesKey(key)

}

Float::class -> {

floatPreferencesKey(key)

}

Long::class -> {

longPreferencesKey(key)

}

Set::class -> {

stringSetPreferencesKey(key)

}

else -> {

null

}

}

return dataStore?.data?.map { preferences ->

if (pKey != null) {

(preferences[pKey] as? T) ?: defaultValue

} else {

val a = preferences[stringPreferencesKey(key)]

if (a != null) {

a.toObject(clazz::class.java) as T

} else {

defaultValue

}

}

}?.first()

}

suspend fun put(key: String, value: Any) {

when (value::class) {

String::class -> {

dataStore?.edit { settings ->

settings[stringPreferencesKey(key)] = value as String

}

}

Int::class -> {

dataStore?.edit { settings ->

settings[intPreferencesKey(key)] = value as Int

}

}

Double::class -> {

dataStore?.edit { settings ->

settings[doublePreferencesKey(key)] = value as Double

}

}

Boolean::class -> {

dataStore?.edit { settings ->

settings[booleanPreferencesKey(key)] = value as Boolean

}

}

Float::class -> {

dataStore?.edit { settings ->

settings[floatPreferencesKey(key)] = value as Float

}

}

Long::class -> {

dataStore?.edit { settings ->

settings[longPreferencesKey(key)] = value as Long

}

}

Set::class -> {

dataStore?.edit { settings ->

settings[stringSetPreferencesKey(key)] = value as Set

}

}

else -> {

dataStore?.edit { settings ->

settings[stringPreferencesKey(key)] = value.toJsonString()

}

}

}

}

suspend fun getMessageEventType():Int? {

return messageEventDataStore?.data?.map {

it.type

}?.first()

}

suspend fun getMessageEventData():String? {

return messageEventDataStore?.data?.map {

it.message

}?.first()

}

suspend fun getMessageEvent():MessageEvent? {

return messageEventDataStore?.data?.map {

it

}?.first()

}

suspend fun putMessageEvent(message:String) {

messageEventDataStore?.updateData {

it.toBuilder()

.setType(it.type)

.setMessage(message)

.build()

}

}

suspend fun putMessageEvent(type:Int) {

messageEventDataStore?.updateData {

it.toBuilder()

.setType(type)

.setMessage(it.message)

.build()

}

}

suspend fun putMessageEvent(type:Int, message:String) {

messageEventDataStore?.updateData {

it.toBuilder()

.setType(type)

.setMessage(message)

.build()

}

}

}

5 举例使用

5.1 创建 DataStore 存储工具子类

object IPDataStore :DataStoreBase("ip"){

}

5.2 基本使用

lifecycleScope.launch {

Log.i("ip", IPDataStore.getString("ip")?:"null")

Log.i("message_event", IPDataStore.getMessageEventType().toString())

Log.i("message_event", IPDataStore.getMessageEventData().toString())

val r = withContext(Dispatchers.IO){

try {

runHttp("http://ip-api.com/json")

} catch (e: Exception) {

e.printStackTrace()

}

}

if (r is String) {

IPDataStore.put("ip", r)

IPDataStore.putMessageEvent(12, r)

IPDataStore.getString("ip")?.let {

Log.i("ip", it?:"null")

}

}

Log.i("message_event", IPDataStore.getMessageEventType().toString())

Log.i("message_event", IPDataStore.getMessageEventData().toString())

IPDataStore.getMessageEvent()?.let {

Log.i("message_event", it.toString())

}

Log.i("ip", "获取完成")

}

var client = OkHttpClient()

fun runHttp(url: String): String? {

val request: Request = Request.Builder()

.url(url)

.build()

client.newCall(request).execute().use { response -> return response.body!!.string() }

}

6 混淆

-keepclassmembers class * extends androidx.datastore.preferences.protobuf.GeneratedMessageLite {

;

}

datastore java_Android 使用DataStore存储数据相关推荐

  1. 2021年大数据HBase(十三):HBase读取和存储数据的流程

    全网最详细的大数据HBase文章系列,强烈建议收藏加关注! 新文章都已经列出历史文章目录,帮助大家回顾前面的知识重点. 目录 系列历史文章 HBase读取和存储数据的流程 一.HBase读取数据的流程 ...

  2. .pgr照片文件解析,C++与Java存储数据差别大小端模式

    一..pgr是什么? .pgr文件是二进制的图像文件,可以用普通的文本文件打开,或者查看十六进制的文本信息: 读取需要了解~~~非常重要 !!! 基本数据类型的大小端存储模式 表头Header 详细信 ...

  3. string生成固定长度的哈希_Redis 选择Hash还是String 存储数据?

    点击上方"Java之间",选择"置顶或者星标" 你关注的就是我关心的! 作者:goodspeed 微信公众号:四月(ID:hiiiapril) 在stackov ...

  4. 在python中使用json格式存储数据

    在python中使用json格式存储数据 代码如下: import jsonlist1 = [{'A': [1, 2, 3, 4, 5, 6], 'B': [3, 4, 5, 6, 7]},{'C': ...

  5. android studio数据库存储数据,如何使用API​​ 23在android studio中的数据库中存储数据?...

    大多数时候我不会发布任何内容,因为我可以在其他帖子中找到我需要的所有内容,但是现在我已经有几天了,您如何在数据库中存储任何内容?这是我的Java代码如何使用API​​ 23在android studi ...

  6. 关于外部存储器件对存储数据的管理。

    一引子 :需要大量存储数据时,一般都不会使用单片机内部存储资源(单片机内部的eerom或者flash模拟eeprom只适合存储少量的数据).一般是通过I2C/SPI接口外部扩展eeprom或者flas ...

  7. 使用嵌入式关系型SQLite数据库存储数据

    除了可以使用文件或SharedPreferences存储数据,还可以选择使用SQLite数据库存储数据. 在Android平台上,集成了一个嵌入式关系型数据库-SQLite,SQLite3支持 NUL ...

  8. android的数据存储方式有哪几种方式,Android存储数据的5种方式

    第一种:SharedPreferences 1.使用键值对的方式存储数据 2.通常用于:保存用户的偏好设置.选择是否保存密码.记录文档阅读的位置等 3.实现方式(写入): a).获取SharedPre ...

  9. 前端 在浏览器端存储数据

    在前端中存储数据大致有三种模式: 1:cookie:但是cookie的空间只有4k,所以很少使用: 2:sessionStorage: 是在本地存储数据,其空间有最多可以达到5M,但是生命周期是浏览器 ...

  10. 【转】Android使用嵌入式关系型SQLite数据库存储数据【学习记录】

    为什么80%的码农都做不了架构师?>>>    除了可以使用文件或SharedPreferences存储数据,还可以选择使用SQLite数据库存储数据. 在Android平台上,集成 ...

最新文章

  1. PTA基础编程题目集-6-9 统计个位数字
  2. 查找局域网中的DHCP服务器
  3. 集群(三)——haproxy+nginx搭建web集群
  4. JS过滤表单数据中的特殊字符
  5. JavaScript操作大全整理(思维导图三--函数基础)
  6. java grpc 客户端处理 go 服务端多返回值_grpc基础实践(二)
  7. 【Asp.Net】C#中checked关键字的应用
  8. 软件测试 学习之路 计算机基础
  9. 今晚直播丨国产数据库入门:openGauss数据库的基本管理和SQL语句入门
  10. 深度学习 --- 受限玻尔兹曼机RBM(MCMC接受率详解)
  11. 美化下拉框select箭头部分(不彻底)
  12. 一些抄来的冷知识...
  13. 【嵌入式】牧马人G3 电子竞技鼠标拆解分析
  14. 项目引入船讯网海图插件
  15. CentOS6.5挂载大于2TB的磁盘使用parted和GPT类型
  16. Idea如何配置svn或集成svn。
  17. linux里shell的心得,Shell学习心得(一):变量
  18. 百度云主机使用WordPress建站ideashare.club过程总结与那些坑
  19. 单片机的电子电路基本知识
  20. nullspace matlab,用numpy计算零空间的有理基

热门文章

  1. su 无法切换账户(密码正确)一直提示Authentication failure(认证失败)
  2. 利用laravel框架创建todos
  3. 英雄联盟商城登录界面
  4. 京东商城发现了一枚Bug
  5. 用python做探索性因子分析(Exploratory Factor Analysis,EFA)全代码
  6. 优质短信api接口具备的特点
  7. face_recognition库的使用
  8. 大数据平台以及一些核心组件介绍
  9. 生态 | 国内数据库领域权威学术会议NDBC 2020成功举办,人大金仓受邀参会并发表主题演讲...
  10. 计算机读不出光盘,光驱读不出光盘,小编教你电脑光盘不能被识别怎么解决