赞
踩
谷歌自2020年开始推出datastore旨在替代原有SharedPreferences,解决SharedPreferences的不足
一、DataStore 相比于 SharedPreferences 优点
1. DataStore 是基于 Flow 实现的,所以保证了在主线程的安全性。
2. 以事务方式处理更新数据,事务有四大特性(原子性、一致性、 隔离性、持久性)。
3. 可以监听到操作成功或者失败结果。
5. SharedPreferences第一次加载数据时需要全量加载,当数据量大时可能会阻塞UI线程造成卡顿
6.SharedPreferencesh在执行commit() / apply()操作可能会造成ANR问题
7.相对于SharedPreferences体积更小
二、datastroe使用教程:
1.引用datastore-preferences、datastore-preferences-core库
- object Datastore {
- val preferences = "androidx.datastore:datastore-preferences:${DependencyVersionManager.datastore}"
- val preferences_core = "androidx.datastore:datastore-preferences-core:${DependencyVersionManager.datastore}"
- }
2.根据项目中SharedPreferences保存路径替换成datastore路径
通过SharedPreferencesMigration
迁移类,只要从工具类中执行了独写操作,都会从SharedPreferences路径中copy一份至datastore路径下,然后自动删除原文件
- private val Context.dataStore by preferencesDataStore(
- name = Constants.Prefs.DATA_STORE_NAME,//datastore 路径
- produceMigrations = { context ->
- listOf(SharedPreferencesMigration(context, Constants.Prefs.PREFRENCE_NAME))//SharedPreferences 路径
- }
- )
3.根据不同的数据类型对datastore进行封装
- object EasyDataStore {
-
- /**
- * 存数据
- */
- @Suppress("UNCHECKED_CAST")
- fun <T> putData(context: Context, key: String, value: T) {
- runBlocking {
- when (value) {
- is Int -> putIntData(context, key, value)
- is Long -> putLongData(context, key, value)
- is String -> putStringData(context, key, value)
- is Boolean -> putBooleanData(context, key, value)
- is Float -> putFloatData(context, key, value)
- is Double -> putDoubleData(context, key, value)
- else -> throw IllegalArgumentException("This type cannot be saved to the Data Store")
- }
- }
- }
-
- /**
- * 取数据
- */
- @Suppress("UNCHECKED_CAST")
- fun <T> getData(context: Context, key: String, defaultValue: T): T {
- val data = when (defaultValue) {
- is Int -> getIntData(context, key, defaultValue)
- is Long -> getLongData(context, key, defaultValue)
- is String -> getStringData(context, key, defaultValue)
- is Boolean -> getBooleanData(context, key, defaultValue)
- is Float -> getFloatData(context, key, defaultValue)
- is Double -> getDoubleData(context, key, defaultValue)
- else -> throw IllegalArgumentException("This type cannot be saved to the Data Store")
- }
- return data as T
- }
-
- /**
- * 清空数据
- */
- fun clearData(context: Context) = runBlocking { context.dataStore.edit { it.clear() } }
-
-
- /**
- * 存放Int数据
- */
- private suspend fun putIntData(context: Context, key: String, value: Int) = context.dataStore.edit {
- it[intPreferencesKey(key)] = value
- }
-
- /**
- * 存放Long数据
- */
- private suspend fun putLongData(context: Context, key: String, value: Long) = context.dataStore.edit {
- it[longPreferencesKey(key)] = value
- }
-
- /**
- * 存放String数据
- */
- private suspend fun putStringData(context: Context, key: String, value: String) = context.dataStore.edit {
- it[stringPreferencesKey(key)] = value
- }
-
- /**
- * 存放Boolean数据
- */
- private suspend fun putBooleanData(context: Context, key: String, value: Boolean) = context.dataStore.edit {
- it[booleanPreferencesKey(key)] = value
- }
-
- /**
- * 存放Float数据
- */
- private suspend fun putFloatData(context: Context, key: String, value: Float) = context.dataStore.edit {
- it[floatPreferencesKey(key)] = value
- }
-
- /**
- * 存放Double数据
- */
- private suspend fun putDoubleData(context: Context, key: String, value: Double) = context.dataStore.edit {
- it[doublePreferencesKey(key)] = value
- }
-
- /**
- * 取出Int数据
- */
- private fun getIntData(context: Context, key: String, default: Int = 0): Int = runBlocking {
- return@runBlocking context.dataStore.data.map {
- it[intPreferencesKey(key)] ?: default
- }.first()
-
- }
-
- /**
- * 取出Long数据
- */
- private fun getLongData(context: Context, key: String, default: Long = 0): Long = runBlocking {
- return@runBlocking context.dataStore.data.map {
- it[longPreferencesKey(key)] ?: default
- }.first()
- }
-
- /**
- * 取出String数据
- */
- private fun getStringData(context: Context, key: String, default: String? = null): String = runBlocking {
- return@runBlocking context.dataStore.data.map {
- it[stringPreferencesKey(key)] ?: default
- }.first()!!
- }
-
- /**
- * 取出Boolean数据
- */
- private fun getBooleanData(context: Context, key: String, default: Boolean = false): Boolean = runBlocking {
- return@runBlocking context.dataStore.data.map {
- it[booleanPreferencesKey(key)] ?: default
- }.first()
- }
-
- /**
- * 取出Float数据
- */
- private fun getFloatData(context: Context, key: String, default: Float = 0.0f): Float = runBlocking {
- return@runBlocking context.dataStore.data.map {
- it[floatPreferencesKey(key)] ?: default
- }.first()
- }
-
- /**
- * 取出Double数据
- */
- private fun getDoubleData(context: Context, key: String, default: Double = 0.00): Double = runBlocking {
- return@runBlocking context.dataStore.data.map {
- it[doublePreferencesKey(key)] ?: default
- }.first()
- }
-
- }
4.在需要对数据进行读写的地方分别调用getData和putData
5.完整Datastore工具类代码见下:
- package com.ovopark.utils
-
- import android.content.Context
- import androidx.datastore.preferences.SharedPreferencesMigration
- import androidx.datastore.preferences.core.*
- import androidx.datastore.preferences.preferencesDataStore
- import com.ovopark.common.Constants
- import kotlinx.coroutines.flow.first
- import kotlinx.coroutines.flow.map
- import kotlinx.coroutines.runBlocking
-
-
- /**
- * 创建人:yaoao
- * 创建日期:2022/6/28.9:37
- * 描述:DataStore封装工具类
- * 修改人:
- * 迭代版本:
- * 迭代说明:
- */
- private val Context.dataStore by preferencesDataStore(
- name = Constants.Prefs.DATA_STORE_NAME,
- produceMigrations = { context ->
- // Since we're migrating from SharedPreferences, add a migration based on the
- // SharedPreferences name
- listOf(SharedPreferencesMigration(context, Constants.Prefs.PREFRENCE_NAME))
- }
- )
- object EasyDataStore {
- /**
- * 存数据
- */
- @Suppress("UNCHECKED_CAST")
- fun <T> putData(context: Context, key: String, value: T) {
- runBlocking {
- when (value) {
- is Int -> putIntData(context, key, value)
- is Long -> putLongData(context, key, value)
- is String -> putStringData(context, key, value)
- is Boolean -> putBooleanData(context, key, value)
- is Float -> putFloatData(context, key, value)
- is Double -> putDoubleData(context, key, value)
- else -> throw IllegalArgumentException("This type cannot be saved to the Data Store")
- }
- }
- }
- /**
- * 取数据
- */
- @Suppress("UNCHECKED_CAST")
- fun <T> getData(context: Context, key: String, defaultValue: T): T {
- val data = when (defaultValue) {
- is Int -> getIntData(context, key, defaultValue)
- is Long -> getLongData(context, key, defaultValue)
- is String -> getStringData(context, key, defaultValue)
- is Boolean -> getBooleanData(context, key, defaultValue)
- is Float -> getFloatData(context, key, defaultValue)
- is Double -> getDoubleData(context, key, defaultValue)
- else -> throw IllegalArgumentException("This type cannot be saved to the Data Store")
- }
- return data as T
- }
- /**
- * 清空数据
- */
- fun clearData(context: Context) = runBlocking { context.dataStore.edit { it.clear() } }
- /**
- * 存放Int数据
- */
- private suspend fun putIntData(context: Context, key: String, value: Int) = context.dataStore.edit {
- it[intPreferencesKey(key)] = value
- }
- /**
- * 存放Long数据
- */
- private suspend fun putLongData(context: Context, key: String, value: Long) = context.dataStore.edit {
- it[longPreferencesKey(key)] = value
- }
- /**
- * 存放String数据
- */
- private suspend fun putStringData(context: Context, key: String, value: String) = context.dataStore.edit {
- it[stringPreferencesKey(key)] = value
- }
- /**
- * 存放Boolean数据
- */
- private suspend fun putBooleanData(context: Context, key: String, value: Boolean) = context.dataStore.edit {
- it[booleanPreferencesKey(key)] = value
- }
- /**
- * 存放Float数据
- */
- private suspend fun putFloatData(context: Context, key: String, value: Float) = context.dataStore.edit {
- it[floatPreferencesKey(key)] = value
- }
- /**
- * 存放Double数据
- */
- private suspend fun putDoubleData(context: Context, key: String, value: Double) = context.dataStore.edit {
- it[doublePreferencesKey(key)] = value
- }
- /**
- * 取出Int数据
- */
- private fun getIntData(context: Context, key: String, default: Int = 0): Int = runBlocking {
- return@runBlocking context.dataStore.data.map {
- it[intPreferencesKey(key)] ?: default
- }.first()
- }
- /**
- * 取出Long数据
- */
- private fun getLongData(context: Context, key: String, default: Long = 0): Long = runBlocking {
- return@runBlocking context.dataStore.data.map {
- it[longPreferencesKey(key)] ?: default
- }.first()
- }
- /**
- * 取出String数据
- */
- private fun getStringData(context: Context, key: String, default: String? = null): String = runBlocking {
- return@runBlocking context.dataStore.data.map {
- it[stringPreferencesKey(key)] ?: default
- }.first()!!
- }
- /**
- * 取出Boolean数据
- */
- private fun getBooleanData(context: Context, key: String, default: Boolean = false): Boolean = runBlocking {
- return@runBlocking context.dataStore.data.map {
- it[booleanPreferencesKey(key)] ?: default
- }.first()
- }
- /**
- * 取出Float数据
- */
- private fun getFloatData(context: Context, key: String, default: Float = 0.0f): Float = runBlocking {
- return@runBlocking context.dataStore.data.map {
- it[floatPreferencesKey(key)] ?: default
- }.first()
- }
- /**
- * 取出Double数据
- */
- private fun getDoubleData(context: Context, key: String, default: Double = 0.00): Double = runBlocking {
- return@runBlocking context.dataStore.data.map {
- it[doublePreferencesKey(key)] ?: default
- }.first()
- }
- }
注意: SharedPreferences有remove方法可以单独对一些键进行删除操作,但是对datastore查找源码并没有此类方法,只能对键进行置空操作
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。