【Android】Jetpack 数据存储首选项

前言

在这篇文章中,我们将了解为什么需要 Jetpack DataStore Preferences,了解如何在我们的 Android 应用程序中实现 Jetpack DataStore Preferences,以及如何将 SharedPreferences 迁移到 DataStore Preferences。

我将分享我从 Android 官方文档中学到的东西,以及我为什么根据我的实践经验推荐新的 Jetpack DataStore。

本文章中要涵盖的主题:

  • 为什么选择 Jetpack 数据存储?
  • SharedPreferences 与 DataStore 首选项
  • 实施 Jetpack 数据存储首选项
  • 从 SharedPreferences 迁移到 DataStore Preferences

首先,为什么要使用这个新的 Jetpack DataStore?

为什么选择 Jetpack 数据存储?

根据官方文档:

  • Jetpack DataStore 是一种新的改进的数据存储解决方案,旨在取代 SharedPreferences。
  • 它建立在Kotlin Coroutines和 Flow 之上。
  • 数据以异步、一致和事务方式存储,克服了 SharedPreferences 的大部分缺点。

上面提到的改进是很大的。

我会告诉你一个原因,为什么我会根据我的实践经验推荐新的 Jetpack DataStore。

我正在开发一个下载量超过 2 亿次的 Android 应用程序,该应用程序在 Google Play 商店中的使用时间超过 7 年。在这段漫长的时间里,该应用程序经历了巨大的发展,许多版本和许多错误修复。

因此,在某个时候,应用程序开始出现 ANR(应用程序无响应)。

ANR 的原因:应用程序正在 UI 线程上执行长时间运行的任务。(超过 5 秒)。

为什么会出现这个 ANR?

主要原因是我们的共享首选项文件变得太大,因为我们不断地一个接一个地添加新的键值。我们试图在应用程序在 UI 线程上打开后立即访问特定键的值。但问题是,当您第一次访问 SharedPreferences 时,它会读取整个文件,将数据带到内存中。对我们来说,这发生在 UI Thread 上。

这是一个 I/O 操作。这可能需要时间。对于我们案例中的较大文件,它会导致 ANR。

我们为此构建了自己的解决方案。这超出了本博客的范围。我可能会计划一个关于该解决方案的详细博客。

Jetpack DataStore 的当前实现不鼓励在 UI Thread 上读取数据。这是我非常喜欢的一点。

现在,让我们谈谈 SharedPreferences 与 DataStore Preferences。

SharedPreferences 与 DataStore 首选项

以下是 SharedPreferences 和 DataStore Preferences 之间的区别:

两者都提供异步 API。
SharedPreferences 提供了一个简单的同步 API,但在 UI 线程上调用并不安全。DataStore Preferences 不鼓励这样做。
DataStore 首选项中保证了一致性。
DataStore 首选项中支持错误处理。
DataStore Preferences 默认支持 Kotlin Coroutines Flow API。
这就是 DataStore Preferences 是对 SharedPreferences 的改进解决方案的原因。

现在,让我们进入实现部分。

实施 Jetpack 数据存储首选项

在您的应用级别 build.gradle 中添加以下依赖项。

implementation “androidx.datastore:datastore-preferences:1.0.0-alpha01”
注意:确保使用最新版本以获得最稳定的版本。

现在,类似于 SharedPreferences 对象,我们需要创建 DataStore Preferences 对象。

val dataStore: DataStore<Preferences> =
    context.createDataStore(name = "mindorks-data-store-prefs")

然后,我们创建两个扩展函数来使用它们来读取和写入数据。这只是为了方便。

fun <T> DataStore<Preferences>.getValueFlow(
    key: Preferences.Key<T>,
    defaultValue: T
): Flow<T> {
    return this.data
        .catch { exception ->
            if (exception is IOException) {
                emit(emptyPreferences())
            } else {
                throw exception
            }
        }.map { preferences ->
            preferences[key] ?: defaultValue
        }
}

suspend fun <T> DataStore<Preferences>.setValue(key: Preferences.Key<T>, value: T) {
    this.edit { preferences ->
        preferences[key] = value
    }
}

然后,我们创建如下首选项键:

companion object {
    private val USERNAME = preferencesKey<String>("username")
}

现在,将值写入 DataStore Preferences:

viewModelScope.launch {
    dataStore.setValue(USERNAME, "Amit Shekhar")
}
现在,从 DataStore Preferences 中读取数据:

viewModelScope.launch {
    dataStore.getValueFlow(USERNAME, "")
        .collect { value ->
            // use the value
        }
}

在这里,我们可以通过catch在流上使用运算符来处理错误。

viewModelScope.launch {
    dataStore.getValueFlow(USERNAME, "")
        .catch {
            // handle error
        }
        .collect { value ->
            // use the value
        }
}

这就是我们可以在我们的 Android 应用程序中轻松使用它的方式。

现在,让我们谈谈从 SharedPreferences 到 DataStore Preferences 的迁移。

从 SharedPreferences 迁移到 DataStore Preferences

当涉及到迁移时,DataStore 会为我们处理。我们只需要提供 SharedPreferences 的名称。例如,如果“ mindorks-prefs ”是 SharedPreferences 的名称,我们必须像下面这样:

val dataStore: DataStore<Preferences> =
    context.createDataStore(
        name = "mindorks-data-store-prefs",
        migrations = listOf(SharedPreferencesMigration(context, "mindorks-prefs"))
    )

当我们检查SharedPreferencesMigration函数时:

fun SharedPreferencesMigration(
    context: Context,
    sharedPreferencesName: String,
    keysToMigrate: Set<String>? = MIGRATE_ALL_KEYS,
    deleteEmptyPreferences: Boolean = true
)

我们可以看到有更多可用的选项,我们可以根据我们的用例使用它们。

这种从 SharedPreferences 迁移到 DataStore Preferences 的方式非常容易。

最后

这里我就分享一份资料,希望可以帮助到大家提升进阶。

内容包含:Android学习PDF+架构视频+面试文档+源码笔记高级架构技术进阶脑图、Android开发面试专题资料,高级进阶架构资料 这几块的内容。分享给大家,非常适合近期有面试和想在技术道路上继续精进的朋友。

如果你有需要的话,可以扫描下方二维码,免费获取Android学习PDF+架构视频+面试文档+源码笔记领取方式

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值