jetpack数据库_jetpack数据存储改进的数据存储系统

jetpack数据库

什么是数据存储?(What’s DataStore?)

Over the years, Android developers have become used to storing small chunks of sensitive user data via shared preferences. This approach has the following drawbacks:

多年来,Android开发人员已经习惯于通过共享首选项来存储敏感用户数据的小块。 此方法具有以下缺点:

  • Sensitive data in shared preferences can be exposed easily

    共享首选项中的敏感数据可以轻松公开
  • It appears safe to invoke the shared-preference operations on a UI thread, but in reality, it’s not (due to the synchronous API that can appear safe to call on the UI thread, no mechanism for signaling errors, lack of a transactional API, and more)

    似乎可以安全地在UI线程上调用共享首选项操作,但实际上并非如此(由于同步API在UI线程上可以安全调用,没有信号传递错误的机制,缺少事务性API,和更多)

DataStore is a library from the Jetpack family that provides a new data-storage solution, probably replacing shared preferences. It’s currently in the alpha stage.

DataStore是Jetpack家族的一个库,它提供了一个新的数据存储解决方案,可能替代了共享首选项。 目前处于alpha阶段。

为什么要使用DataStore? (Why DataStore?)

It’s built using Kotlin coroutines and the Flow API, which makes it more safe and reliable than shared preferences. It offers two different approaches to save data:

它是使用Kotlin协程和Flow API构建的,这使其比共享首选项更加安全可靠。 它提供了两种不同的方法来保存数据:

  • Preferences DataStore: It’s similar to SharedPreferences, in that it has no way to define a schema or to ensure that keys are accessed with the correct type

    Preferences DataStore:它类似于SharedPreferences ,因为它无法定义架构或确保使用正确的类型访问键

  • Proto DataStore: Lets you create a schema using protocol buffers. Using protobufs allows for the persisting of strongly typed data. They’re faster, smaller, simpler, and less ambiguous than XML and other similar data formats.

    Proto DataStore:允许您使用协议缓冲区创建架构。 使用protobuf可以保留强类型数据。 与XML和其他类似的数据格式相比,它们更快,更小,更简单且模棱两可。

In addition to that, when you store key-value pairs, only the keys will be exposed but not the content.

除此之外,当您存储键值对时,将仅公开键,而不公开内容。

数据库与数据存储 (Database vs. DataStore)

DataStore is built to store small data sets; if your requirement involves partial updates, referential integrity, or support for large/complex data sets, you should consider using Room instead of DataStore.

DataStore用于存储小型数据集。 如果您的需求涉及部分更新,参照完整性或对大型/复杂数据集的支持,则应考虑使用Room而不是DataStore。

At the end of this article, you’ll find links to learn how to use the Room database, from its basics to more advanced options.

在本文的结尾,您将找到一些链接,以学习如何使用Room数据库,从基础到更高级的选项。

积分 (Integration)

To use the Jetpack Datastore library, add the following line under the dependencies node in the app-level build.gradle file.

要使用Jetpack数据存储库,请在应用程序级别build.gradle文件中的dependencies节点下添加以下行。

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

让我们开始编码 (Let’s Start Coding)

To better understand how to use DataStore, I took a simple real-time example, where we store an integer that indicates a user’s login status. Here, we have an enum class with all possible stages. Have a look:

为了更好地理解如何使用DataStore,我举了一个简单的实时示例,在该示例中,我们存储一个指示用户登录状态的整数。 在这里,我们有一个包含所有可能阶段的enum类。 看一看:

enum class UserStatus {
    STARTER, ONBOARDING_LEVEL_1, ONBOARDING_LEVEL_2, VERIFIED
}

创建您的数据存储(Create your DataStore)

The next step is to create the DataStore. For this, we need to create a Kotlin class in which we’ll use the context.createDataStore extension function to create the DatasSore. Have a look:

下一步是创建数据存储。 为此,我们需要创建一个Kotlin类,在其中我们将使用context.createDataStore扩展函数来创建DatasSore。 看一看:

class PreferenceManager(context: Context){
    private val dataStore = context.createDataStore(name = "prefernce_name")
}

创建密钥(Creating keys)

We’ll create the preferencesKey inline function by defining the result type. Have a look:

我们将通过定义结果类型来创建preferencesKey内联函数。 看一看:

companion object {
val USER_STATUS = preferencesKey<Int>("user_status")
}

保存和检索数据 (Save and Retrieve Data)

Now that we’ve created our DataStore andkeys, it’s time to save the user’s status. We’ll save an integer with values 1, 2, 3, and 4 representing STARTER, ONBOARDING_LEVEL_1, ONBOARDING_LEVEL_2, and VERIFIED, respectively.

现在,我们已经创建了DataStore和键,是时候保存用户的状态了。 我们将保存的值1,2,3和4表示整数STARTERONBOARDING_LEVEL_1ONBOARDING_LEVEL_2 ,和VERIFIED分别。

(Save)

To save key-value pairs in the DataStore file, we have to use the edit function, which updates the value. Here, we use the suspend function to save values. Have a look:

要将键值对保存在DataStore文件中,我们必须使用edit函数来更新值。 在这里,我们使用suspend函数来保存值。 看一看:

suspend fun setUserStatus(userStatus: UserStatus) {
    dataStore.edit { preferences ->
        preferences[USER_STATUS] = when (userStatus) {
            UserStatus.STARTER -> 1
            UserStatus.ONBOARDING_LEVEL_1 -> 2
            UserStatus.ONBOARDING_LEVEL_2 -> 3
            UserStatus.VERIFIED -> 4
        }
    }
}

取回(Retrieve)

To retrieve values from the DataStore, we use the Flow API. One of the main advantages of using Flow is every time a new value is updated in the DataStore, we get notified. So we no longer need to check for updated values anymore.

要从DataStore检索值,我们使用Flow API。 使用Flow的主要优点之一是,每次在DataStore中更新新值时,我们都会得到通知。 因此,我们不再需要检查更新的值。

val userStatusFlow: Flow<UserStatus> = dataStore.data
        .catch {
            if (it is IOException) {
                it.printStackTrace()
                emit(emptyPreferences())
            } else {
                throw it
            }
        }
        .map { preference ->
            val userStatus = preference[USER_STATUS] ?: 1


            when (userStatus) {
                1 -> UserStatus.STARTER
                2 -> UserStatus.ONBOARDING_LEVEL_1
                3 -> UserStatus.ONBOARDING_LEVEL_2
                4 -> UserStatus.VERIFIED
                else -> UserStatus.STARTER
            }
        }

Instead of handing the integer to the user-status case at the call site, we can use functions like map to transform the data into an appropriate data type.Now, let’s bring the pieces together so they make more sense. Have a look:

除了将整数传递给调用站点的用户状态外,我们还可以使用诸如map函数将数据转换为适当的数据类型。现在,让我们将各个部分放在一起以使它们更有意义。 看一看:

enum class UserStatus {
    STARTER, ONBOARDING_LEVEL_1, ONBOARDING_LEVEL_2, VERIFIED
}


class PreferenceManager(context: Context) {


    private val dataStore = context.createDataStore(name = "prefernce_name")


    val userStatusFlow: Flow<UserStatus> = dataStore.data
        .catch {
            if (it is IOException) {
                it.printStackTrace()
                emit(emptyPreferences())
            } else {
                throw it
            }
        }
        .map { preference ->
            val userStatus = preference[USER_STATUS] ?: 1


            when (userStatus) {
                1 -> UserStatus.STARTER
                2 -> UserStatus.ONBOARDING_LEVEL_1
                3 -> UserStatus.ONBOARDING_LEVEL_2
                4 -> UserStatus.VERIFIED
                else -> UserStatus.STARTER
            }
        }


    suspend fun setUserStatus(userStatus: UserStatus) {
        dataStore.edit { preferences ->
            preferences[USER_STATUS] = when (userStatus) {
                UserStatus.STARTER -> 1
                UserStatus.ONBOARDING_LEVEL_1 -> 2
                UserStatus.ONBOARDING_LEVEL_2 -> 3
                UserStatus.VERIFIED -> 4
            }
        }
    }


    companion object {
        val USER_STATUS = preferencesKey<Int>("user_status")
    }
}

从Android组件访问(Access From Android Components)

Now that we’re done with the preference manager, let’s figure out how to invoke setUserStatus from an Android activity. Have a look:

既然我们已经完成了首选项管理器,那么让我们弄清楚如何从Android活动中调用setUserStatus 。 看一看:

fun saveuserStatus(status : Int){
  lifecycleScope.launch {
    when (status) {
        1 -> preferenceManager.setUserStatus(UserStatus.STARTER)
        2 -> preferenceManager.setUserStatus(UserStatus.ONBOARDING_LEVEL_1)
        3 -> preferenceManager.setUserStatus(UserStatus.ONBOARDING_LEVEL_2)
        4 -> preferenceManager.setUserStatus(UserStatus.VERIFIED)
    }
  }
}

As setUserStatus is a suspend function, we’ve used a lifecycleScope to launch a coroutine.

由于setUserStatus是一个暂停函数,因此我们使用了lifecycleScope启动协程。

Retrieving the data center’s data is similar; here, we use collectLatest from the Flow API by warping it with a lifecycleScope. Have a look:

检索数据中心的数据是类似的; 在这里,我们使用collectLatest从流API通过用扭曲它lifecycleScope 。 看一看:

lifecycleScope.launch(Dispatchers.Main) {
    preferencemanager.userStatusFlow.collectLatest { userStatus-> 
        when (userStatus) {
            UserStatus.STARTER -> {/* TODO */}
            UserStatus.ONBOARDING_LEVEL_1 -> {/* TODO */}
            UserStatus.ONBOARDING_LEVEL_2 -> {/* TODO */}
            UserStatus.VERIFIED -> {/* TODO */}
        }
    }
}

结论(Conclusion)

That’s all for now. Hope you learned something useful. Thanks for reading!

目前为止就这样了。 希望你学到了一些有用的东西。 谢谢阅读!

Jetpack库资源 (Jetpack library resources)

房间图书馆资源 (Room library resources)

翻译自: https://medium.com/better-programming/jetpack-datastore-improved-data-storage-system-adec129b6e48

jetpack数据库

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值