当前位置:   article > 正文

Android使用 Jetpack DataStore 进行数据存储实例_import androidx.datastore.core.datastore

import androidx.datastore.core.datastore

参考Android官方文档 使用 Jetpack DataStore 进行数据存储 以及 官网介绍 Android DataStore 写了一个demo实例。

一、Preferences DataStore

1.需要kotlin的开发环境,因为DataStore内部是用协程实现的

2.使用时需添加依赖

  1. dependencies {
  2. implementation "androidx.datastore:datastore-preferences:1.0.0-alpha05"
  3. }

3.代码中使用,如下例:

  1. package com.xxx.androidstudydemo.datastore
  2. import android.util.Log
  3. import androidx.datastore.core.DataStore
  4. import androidx.datastore.preferences.createDataStore
  5. import androidx.datastore.preferences.core.Preferences
  6. import androidx.datastore.preferences.core.edit
  7. import androidx.datastore.preferences.core.preferencesKey
  8. import com.hxy.androidstudydemo.DemoApp
  9. import kotlinx.coroutines.flow.first
  10. import kotlinx.coroutines.flow.map
  11. import kotlinx.coroutines.runBlocking
  12. object DataStoreHelper {
  13. private val TAG = "DataStoreHelper"
  14. //1.创建Preference DataStore
  15. private val dataStore: DataStore<Preferences> = DemoApp.mContext.createDataStore(
  16. name = "data_store_demo"
  17. )
  18. //2.定义键
  19. private val TEST_KEY01 = preferencesKey<String>("test_key01")
  20. private val TEST_KEY02 = preferencesKey<Int>("test_key02")
  21. private val TEST_KEY03 = preferencesKey<Boolean>("test_key03")
  22. //3.设置键值
  23. suspend fun setTestKey01(value:String ) {
  24. dataStore.edit { preferences -> preferences[TEST_KEY01] = value }
  25. }
  26. suspend fun setTestKey02(value:Int ) {
  27. dataStore.edit { preferences -> preferences[TEST_KEY02] = value }
  28. }
  29. suspend fun setTestKey01(value:Boolean ) {
  30. dataStore.edit { preferences -> preferences[TEST_KEY03] = value }
  31. }
  32. //4.获取值
  33. suspend fun getTestKey01(): String {
  34. return dataStore.data.map { preferences -> preferences[TEST_KEY01] }.first() ?: ""
  35. }
  36. suspend fun getTestKey02(): Int {
  37. return dataStore.data.map { preferences -> preferences[TEST_KEY02] }.first() ?: 0
  38. }
  39. /*
  40. 错误写法,使用collect的话Flow一直不结束,所以协程一直挂起状态,得不到值
  41. suspend fun getTestKey02(): Int {
  42. var value: Int = 0
  43. dataStore.data.map { preferences -> preferences[TEST_KEY02] }.collect { value = it?: 0 }
  44. return value
  45. }*/
  46. suspend fun getTestKey03(): Boolean {
  47. return dataStore.data.map { preferences -> preferences[TEST_KEY03] }.first() ?: false
  48. }
  49. fun testFun() = runBlocking {
  50. Log.d(TAG, "字串初始值:" + getTestKey01())
  51. setTestKey01("Hello world!")
  52. Log.d(TAG, "字串终值:" + getTestKey01())
  53. Log.d(TAG, "数初始值:" + getTestKey02())
  54. setTestKey02(666)
  55. Log.d(TAG, "数终值:" + getTestKey02())
  56. Log.d(TAG, "布尔初始值:" + getTestKey03())
  57. setTestKey01(true)
  58. Log.d(TAG, "布尔终值:" + getTestKey03())
  59. }
  60. }

这里需要强调的一点就是在获取值的时候,因为是采用的Flow的机制实现的,所以如果采用collect的方式来获取值会出现Flow一直不取消,协程一直挂起等待的状态,得不到值。这里应该采用flow.first()的方式获取第一个值,然后从API介绍可知此方法会自动自动取消collect。

使用上跟SharedPreference很类似,也很简单,Android官方推荐使用,但目前还处于测试版本。

二、Proto DataStore

环境配置:基于AndroidStudio4.1.2

1.先AS中安装一个插件Protocol Buffer Editor,方便proto文件的编写和格式化

2.配置proto的编译环境:

a)工程目录build.gradle中添加插件 

  1. dependencies {
  2. classpath 'com.google.protobuf:protobuf-gradle-plugin:0.8.14'
  3. }

b)模块目录build.gradle中加入如下内容:原有内容以“...”替代,对照层级加入相应配置

  1. plugins {
  2. .......
  3. id 'com.google.protobuf'
  4. }
  5. android {
  6. ........
  7. sourceSets {
  8. main {
  9. proto {
  10. srcDir 'src/main/proto'
  11. include '**/*.proto'
  12. }
  13. java {
  14. srcDir 'src/main/java'
  15. }
  16. }
  17. }
  18. }
  19. dependencies {
  20. ..........
  21. implementation "androidx.datastore:datastore:1.0.0-alpha05"
  22. implementation "com.google.protobuf:protobuf-javalite:3.14.0"
  23. }
  24. protobuf {
  25. protoc {
  26. artifact = "com.google.protobuf:protoc:3.14.0"
  27. }
  28. // Generates the java Protobuf-lite code for the Protobufs in this project. See
  29. // https://github.com/google/protobuf-gradle-plugin#customizing-protobuf-compilation
  30. // for more information.
  31. generateProtoTasks {
  32. all().each { task ->
  33. task.builtins {
  34. java {
  35. option 'lite'
  36. }
  37. }
  38. }
  39. }
  40. }

3.编写proto文件,路径为上述配置中的src/main/proto下,这个可以修改,命名为xxx.proto,并重新rebuild project,其会在build->generated/source/下生成此proto相关的java代码

  1. syntax = "proto3";
  2. option java_package = "com.hxy.androidstudydemo.datastore";
  3. option java_multiple_files = true;
  4. message TestData {
  5. int32 test_id = 1;
  6. string msg = 2;
  7. bool enable = 3;
  8. }

4.将生成的与proto相匹配的java类序列化

  1. object TestDataSerializer : Serializer<TestData> {//TestData即为编译生成的java类
  2. override fun readFrom(input: InputStream): TestData {
  3. return TestData.parseFrom(input)//序列化过程只需简单的对应一下
  4. }
  5. override fun writeTo(t: TestData, output: OutputStream) {
  6. t.writeTo(output)
  7. }
  8. override val defaultValue: TestData
  9. get() = TestData.getDefaultInstance()
  10. }

5.使用4中的序列化文件创建Proto DataStore实例,如下代码;

  1. class TestProtoDataStore {
  2. private val dataStore by lazy {
  3. DemoApp.mContext.createDataStore(
  4. fileName = FILENAME,
  5. serializer = TestDataSerializer//上一步序列化后的类
  6. )
  7. }
  8. suspend fun setTestDataId(id: Int) {
  9. dataStore.updateData {
  10. it.toBuilder().setTestId(id).build()
  11. }
  12. }
  13. suspend fun getTestDataId(): Int {
  14. return dataStore.data.map { it.testId }.first()
  15. }
  16. suspend fun setTestDataMsg(msg: String) {
  17. dataStore.updateData {
  18. it.toBuilder().setMsg(msg).build()
  19. }
  20. }
  21. suspend fun getTestDataMsg(): String {
  22. return dataStore.data.map { it.msg }.first()
  23. }
  24. suspend fun setTestDataEnable(bool: Boolean) {
  25. dataStore.updateData {
  26. it.toBuilder().setEnable(bool).build()
  27. }
  28. }
  29. suspend fun isTestDataEnable(): Boolean {
  30. return dataStore.data.map { it.enable }.first()
  31. }
  32. suspend fun setTestData(data: TestData) {
  33. dataStore.updateData {
  34. it.toBuilder()
  35. .setTestId(data.testId)
  36. .setEnable(data.enable)
  37. .setMsg(data.msg)
  38. .build()
  39. }
  40. }
  41. suspend fun getTestData(): TestData {
  42. return dataStore.data.first()
  43. }
  44. companion object{
  45. const val FILENAME = "test.pb"
  46. fun testFun() = runBlocking {
  47. val testData = TestData.getDefaultInstance()
  48. }
  49. }
  50. }

接下来就可以像一般类和方法一样使用了。

注意:Preference DataStore和Proto DataStore引用的jar包有区别,如果工程中同时使用了二者,需要将两个包都加进去;请注意到:Preference DataStore创建时使用的是

androidx.datastore.preferences.PreferenceDataStore.Context.createDataStore(name="xxxx")
而Proto DataStore是
androidx.datastore.DataStoreFactory.Context.createDataStore(fileName="xxx.pb",serializer = XXX)

 

源码:CODE.CHINA   Android-studydemo


为什么使用DataStore?

官方给了一张图应该能介绍清楚了:

参考文档:

ProtoBuffer官网 https://developers.google.cn/protocol-buffers

官网介绍 https://developer.android.google.cn/topic/libraries/architecture/datastore#typed-datastore

Android Jetpack 之 DataStore https://blog.csdn.net/zzw0221/article/details/109274610

GitHub上DataStoreSample https://github.com/danledian/DataStoreSample

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家自动化/article/detail/309347
推荐阅读
相关标签
  

闽ICP备14008679号