赞
踩
参考Android官方文档 使用 Jetpack DataStore 进行数据存储 以及 官网介绍 Android DataStore 写了一个demo实例。
1.需要kotlin的开发环境,因为DataStore内部是用协程实现的
2.使用时需添加依赖
- dependencies {
- implementation "androidx.datastore:datastore-preferences:1.0.0-alpha05"
- }
3.代码中使用,如下例:
- package com.xxx.androidstudydemo.datastore
-
- import android.util.Log
- import androidx.datastore.core.DataStore
- import androidx.datastore.preferences.createDataStore
- import androidx.datastore.preferences.core.Preferences
- import androidx.datastore.preferences.core.edit
- import androidx.datastore.preferences.core.preferencesKey
- import com.hxy.androidstudydemo.DemoApp
- import kotlinx.coroutines.flow.first
- import kotlinx.coroutines.flow.map
- import kotlinx.coroutines.runBlocking
-
- object DataStoreHelper {
- private val TAG = "DataStoreHelper"
-
- //1.创建Preference DataStore
- private val dataStore: DataStore<Preferences> = DemoApp.mContext.createDataStore(
- name = "data_store_demo"
- )
- //2.定义键
- private val TEST_KEY01 = preferencesKey<String>("test_key01")
- private val TEST_KEY02 = preferencesKey<Int>("test_key02")
- private val TEST_KEY03 = preferencesKey<Boolean>("test_key03")
- //3.设置键值
- suspend fun setTestKey01(value:String ) {
- dataStore.edit { preferences -> preferences[TEST_KEY01] = value }
- }
- suspend fun setTestKey02(value:Int ) {
- dataStore.edit { preferences -> preferences[TEST_KEY02] = value }
- }
- suspend fun setTestKey01(value:Boolean ) {
- dataStore.edit { preferences -> preferences[TEST_KEY03] = value }
- }
- //4.获取值
- suspend fun getTestKey01(): String {
- return dataStore.data.map { preferences -> preferences[TEST_KEY01] }.first() ?: ""
- }
- suspend fun getTestKey02(): Int {
- return dataStore.data.map { preferences -> preferences[TEST_KEY02] }.first() ?: 0
- }
- /*
- 错误写法,使用collect的话Flow一直不结束,所以协程一直挂起状态,得不到值
- suspend fun getTestKey02(): Int {
- var value: Int = 0
- dataStore.data.map { preferences -> preferences[TEST_KEY02] }.collect { value = it?: 0 }
- return value
- }*/
- suspend fun getTestKey03(): Boolean {
- return dataStore.data.map { preferences -> preferences[TEST_KEY03] }.first() ?: false
- }
-
- fun testFun() = runBlocking {
- Log.d(TAG, "字串初始值:" + getTestKey01())
- setTestKey01("Hello world!")
- Log.d(TAG, "字串终值:" + getTestKey01())
- Log.d(TAG, "数初始值:" + getTestKey02())
- setTestKey02(666)
- Log.d(TAG, "数终值:" + getTestKey02())
- Log.d(TAG, "布尔初始值:" + getTestKey03())
- setTestKey01(true)
- Log.d(TAG, "布尔终值:" + getTestKey03())
- }
- }
这里需要强调的一点就是在获取值的时候,因为是采用的Flow的机制实现的,所以如果采用collect的方式来获取值会出现Flow一直不取消,协程一直挂起等待的状态,得不到值。这里应该采用flow.first()的方式获取第一个值,然后从API介绍可知此方法会自动自动取消collect。
使用上跟SharedPreference很类似,也很简单,Android官方推荐使用,但目前还处于测试版本。
环境配置:基于AndroidStudio4.1.2
1.先AS中安装一个插件Protocol Buffer Editor,方便proto文件的编写和格式化
2.配置proto的编译环境:
a)工程目录build.gradle中添加插件
- dependencies {
- classpath 'com.google.protobuf:protobuf-gradle-plugin:0.8.14'
- }
b)模块目录build.gradle中加入如下内容:原有内容以“...”替代,对照层级加入相应配置
- plugins {
- .......
- id 'com.google.protobuf'
- }
-
- android {
- ........
- sourceSets {
- main {
- proto {
- srcDir 'src/main/proto'
- include '**/*.proto'
- }
- java {
- srcDir 'src/main/java'
- }
- }
- }
- }
-
- dependencies {
- ..........
- implementation "androidx.datastore:datastore:1.0.0-alpha05"
- implementation "com.google.protobuf:protobuf-javalite:3.14.0"
- }
-
- protobuf {
- protoc {
- artifact = "com.google.protobuf:protoc:3.14.0"
- }
-
- // Generates the java Protobuf-lite code for the Protobufs in this project. See
- // https://github.com/google/protobuf-gradle-plugin#customizing-protobuf-compilation
- // for more information.
- generateProtoTasks {
- all().each { task ->
- task.builtins {
- java {
- option 'lite'
- }
- }
- }
- }
- }
3.编写proto文件,路径为上述配置中的src/main/proto下,这个可以修改,命名为xxx.proto,并重新rebuild project,其会在build->generated/source/下生成此proto相关的java代码
- syntax = "proto3";
-
- option java_package = "com.hxy.androidstudydemo.datastore";
- option java_multiple_files = true;
-
- message TestData {
- int32 test_id = 1;
- string msg = 2;
- bool enable = 3;
- }
4.将生成的与proto相匹配的java类序列化
- object TestDataSerializer : Serializer<TestData> {//TestData即为编译生成的java类
- override fun readFrom(input: InputStream): TestData {
- return TestData.parseFrom(input)//序列化过程只需简单的对应一下
- }
-
- override fun writeTo(t: TestData, output: OutputStream) {
- t.writeTo(output)
- }
-
- override val defaultValue: TestData
- get() = TestData.getDefaultInstance()
- }
5.使用4中的序列化文件创建Proto DataStore实例,如下代码;
- class TestProtoDataStore {
- private val dataStore by lazy {
- DemoApp.mContext.createDataStore(
- fileName = FILENAME,
- serializer = TestDataSerializer//上一步序列化后的类
- )
- }
-
- suspend fun setTestDataId(id: Int) {
- dataStore.updateData {
- it.toBuilder().setTestId(id).build()
- }
- }
-
- suspend fun getTestDataId(): Int {
- return dataStore.data.map { it.testId }.first()
- }
-
- suspend fun setTestDataMsg(msg: String) {
- dataStore.updateData {
- it.toBuilder().setMsg(msg).build()
- }
- }
-
- suspend fun getTestDataMsg(): String {
- return dataStore.data.map { it.msg }.first()
- }
-
- suspend fun setTestDataEnable(bool: Boolean) {
- dataStore.updateData {
- it.toBuilder().setEnable(bool).build()
- }
- }
-
- suspend fun isTestDataEnable(): Boolean {
- return dataStore.data.map { it.enable }.first()
- }
-
- suspend fun setTestData(data: TestData) {
- dataStore.updateData {
- it.toBuilder()
- .setTestId(data.testId)
- .setEnable(data.enable)
- .setMsg(data.msg)
- .build()
- }
- }
-
- suspend fun getTestData(): TestData {
- return dataStore.data.first()
- }
-
- companion object{
- const val FILENAME = "test.pb"
- fun testFun() = runBlocking {
- val testData = TestData.getDefaultInstance()
- }
- }
- }
接下来就可以像一般类和方法一样使用了。
注意: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
赞
踩
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。