美文网首页
一文了解DataStore(Preferences)

一文了解DataStore(Preferences)

作者: MakerGaoGao | 来源:发表于2022-08-05 09:40 被阅读0次

    前言

    1. 本篇主要介绍DataStore,包含介绍,使用等。
    2. 本篇会介绍DataStore两种实现Preferences DataStore(主要介绍)和Proto DataStore(后续介绍)。
    3. 本篇也会介绍到DataStore和SharedPreferences的不同之处,以及如何进行迁移。

    简介

    • 首先,DataStore是Jetpack一部分,是一种数据存储解决方案。
    • 其次,DataStore使用协程及flow以异步、一致的方式实现数据的存储。
    • 最后是DataStore的实现,分为Preferences DataStore和Proto DataStore:
      • Preferences DataStore 类似于SharedPreferences,键值对存储,本篇的主要介绍。
      • Proto DataStore 将数据作为自定义数据类型的实例进行存储,基于Google protobuf实现。

    DataStore和SharedPreferences(SP)

    • SP存在的问题:
      • 内存浪费问题,加载的数据会一直存在在内存中。
      • get方法可能会阻塞主线程。
      • apply方法虽然为异步,也可能会发生ANR。
      • SP也无法保证类型安全。
      • SP不支持跨进程。
    • DataStore的特点:
      • 基于协程和Flow实现,保证了主线程的安全性。
      • 以事务的方式进行处理,保证了操作的原子性、一致性、隔离性及持久性。
      • Preferences DataStore可以支持SP的迁移,保证数据的完整性。
    • 说明:
      • 此处只是列出SP存在的问题,并没有SP一无是处的的说法,DataStore在SP的基础上解决了不少的问题,但是也没有说SP存在的问题已经全部解决了。
      • 至少,DataStore在SP的基础上解决了如类型安全、阻塞导致anr等问题,确实这方面优于SP。

    Preferences DataStore

    1. 依赖引入及扩展

    • 依赖引入
    implementation 'androidx.datastore:datastore-preferences:1.0.0'
    
    • 扩展属性,对Contex扩展属性,方便使用。
    val Context.dataStore by preferencesDataStore(name = "data_store")
    

    2. 基本使用:

    编码
                //存储
                dataStore.edit { edit ->
                    edit[stringPreferencesKey("data")] = "123456"
                }
                //读取
               val data =  dataStore.data.first()[stringPreferencesKey("data")]
                Log.d(TAG.TAG,"data is $data")
    
    日志
    2022-08-04 14:38:15.606 13419-13445/edu.test.demo D/Test-TAG: data is 123456
    
    分析:
    • 一眼看起来貌似和SP区别也不大,事实上使用起来区别也确实不大。
    • 区别在于key值不再是String,而是Preferences.Key<String>,当然这是存储string的key,存储别的类型key也不一样。
    • 有一点就是必须在协程中使用,因为edit方法是suspend方法,读取的时候data返回值为flow,操作起来也是在协程中。

    3. 更新:

    代码1(也就是再编辑一遍就覆盖了)如下:
      //存储
                dataStore.edit { edit ->
                    edit[stringPreferencesKey("data")] = "123456"
                }
    
                //读取
               val data =  dataStore.data.first()[stringPreferencesKey("data")]
                Log.d(TAG.TAG,"data is $data")
    
                dataStore.edit { edit ->
                    edit[stringPreferencesKey("data")] = "123456789"
                }
    
                Log.d(TAG.TAG,"data is ${ dataStore.data.first()[stringPreferencesKey("data")]}")
    
    日志如下:
    2022-08-04 14:44:25.651 13552-13579/edu.test.demo D/Test-TAG: data is 123456
    2022-08-04 14:44:25.657 13552-13579/edu.test.demo D/Test-TAG: data is 123456789
    
    代码2 调用update
                 //存储
                dataStore.edit { edit ->
                    edit[stringPreferencesKey("data")] = "123456"
                }
    
                //读取
               val data =  dataStore.data.first()[stringPreferencesKey("data")]
                Log.d(TAG.TAG,"data is $data")
    
                dataStore.updateData {
                    val mutablePreference = it.toMutablePreferences()
                    mutablePreference[stringPreferencesKey("data")] = "123456789"
                    mutablePreference.toPreferences()
                }
    
                Log.d(TAG.TAG,"data is ${ dataStore.data.first()[stringPreferencesKey("data")]}")
    
    分析:
    • 修改和SP也没有太大的却别,我们可以直接edit覆盖,也可以update。

    3. DataStore支持的存储类型:

    DataStore支持的存储类型从key上就可以看出,主要有七种,key类型以及调用方法如下,一眼就能看出来,就不一一
    解释了:
    
    • Preferences.Key<Int> intPreferencesKey
    • Preferences.Key<Double> doublePreferencesKey
    • Preferences.Key<String> stringPreferencesKey
    • Preferences.Key<Boolean> booleanPreferencesKey
    • Preferences.Key<Float> floatPreferencesKey
    • Preferences.Key<Long> longPreferencesKey
    • Preferences.Key<Set<String>> stringSetPreferencesKey

    4. SP到DataStore的迁移

    迁移编码:
    • 主要是在扩展进行迁移,传入sp的文件名。
    val Context.dataStore : DataStore<Preferences> by preferencesDataStore(name = "dataStore_setting",
        produceMigrations = { context ->
            listOf( SharedPreferencesMigration(context, "sp_data"))
        })
    

    迁移之前我们可以看下sp文件,位置为data/data/包名/shared_prefs/sp文件名:


    微信截图_20220804151724.png

    迁移之后,sp文件被删除,datastore文件出现,如下:


    微信截图_20220804152313.png
    验证编码:
      val data = dataStore.data.first()[stringPreferencesKey("mydata")]
               Log.d(TAG.TAG,"sp->datastore,直接读取:$data")
    
    日志如下:
    2022-08-04 15:22:24.062 14131-14157/edu.test.demo D/Test-TAG: sp->datastore,直接读取:mydata123456
    
    分析:
    • 对比可以看出,迁移之后sp文件被删除,出现datastore文件。
    • 编码验证说明已经迁移成功,sp之前存储的值,我们在datastore直接读取了出来。
    • 只有在我们使用dataStore.data.first()的时候,才会进行文件的迁移。

    总结

    • 本篇主要介绍了DataStore的实现分类。
    • 本篇也介绍了DataStore在sp的基础上做了那些优化。
    • 介绍了DataStore的使用,支持数据类型,以及SP到DataStore的迁移。

    相关文章

      网友评论

          本文标题:一文了解DataStore(Preferences)

          本文链接:https://www.haomeiwen.com/subject/kdfpwrtx.html