美文网首页
Jetpack DataStore

Jetpack DataStore

作者: 碎念枫子 | 来源:发表于2022-12-26 12:07 被阅读0次

Jetpack DataStore 是一种数据存储解决方案,允许您使用协议缓冲区存储键值对或类型化对象。DataStore 使用 Kotlin 协程和 Flow 以异步、一致的事务方式存储数据。是kotlin用于替代SharedPreferences的一个手段。

如果您需要支持大型或复杂数据集、部分更新或参照完整性,请考虑使用 Room,而不是 DataStore。DataStore 非常适合简单的小型数据集,但不支持部分更新或引用完整性。

DataStore 提供两种不同的实现:Preferences DataStore 和 Proto DataStore。

  • Preferences DataStore 使用键存储和访问数据。此实现不需要预定义的架构,也不确保类型安全。

  • Proto DataStore 将数据作为自定义数据类型的实例进行存储。此实现要求您使用协议缓冲区来定义架构,但可以确保类型安全。

重要的注意事项

  1. 请勿在同一进程中为给定文件创建多个 DataStore 实例,否则会破坏所有 DataStore 功能。如果给定文件在同一进程中有多个有效的 DataStore,DataStore 在读取或更新数据时将抛出 IllegalStateException

  2. DataStore 的通用类型必须不可变。更改 DataStore 中使用的类型会导致 DataStore 提供的所有保证失效,并且可能会造成严重的、难以发现的 bug。强烈建议您使用可保证不可变性、具有简单的 API 且能够高效进行序列化的协议缓冲区。

  3. 切勿在同一个文件中混用 SingleProcessDataStoreMultiProcessDataStore。如果您打算从多个进程访问 DataStore,请始终使用 MultiProcessDataStore

如何启动DataStore

Preferences DataStore

Preferences DataStore (SharedPreferences like APIs)
 dependencies {
 implementation("androidx.datastore:datastore-preferences:1.0.0")

 // optional - RxJava2 support
 implementation("androidx.datastore:datastore-preferences-rxjava2:1.0.0")

 // optional - RxJava3 support
 implementation("androidx.datastore:datastore-preferences-rxjava3:1.0.0")
 }

 // Alternatively - use the following artifact without an Android dependency.
 dependencies {
 implementation("androidx.datastore:datastore-preferences-core:1.0.0")
 }

Proto DataStore

// Typed DataStore (Typed API surface, such as Proto)
 dependencies {
 implementation("androidx.datastore:datastore:1.0.0")

 // optional - RxJava2 support
 implementation("androidx.datastore:datastore-rxjava2:1.0.0")

 // optional - RxJava3 support
 implementation("androidx.datastore:datastore-rxjava3:1.0.0")
 }

 // Alternatively - use the following artifact without an Android dependency.
 dependencies {
 implementation("androidx.datastore:datastore-core:1.0.0")
 }

混淆

-keepclassmembers class * extends androidx.datastore.preferences.protobuf.GeneratedMessageLite {
 <fields>;
}

使用 Preferences DataStore 存储键值对

Preferences DataStore 实现使用 DataStorePreferences 类将简单的键值对保留在磁盘上。

使用由 preferencesDataStore 创建的属性委托来创建 Datastore<Preferences> 实例。在您的 Kotlin 文件顶层调用该实例一次,便可在应用的所有其余部分通过此属性访问该实例。这样可以更轻松地将 DataStore 保留为单例。此外,如果您使用的是 RxJava,请使用 RxPreferenceDataStoreBuilder。必需的 name 参数是 Preferences DataStore 的名称。

// At the top level of your kotlin file:
val Context.dataStore: DataStore<Preferences> by preferencesDataStore(name = "settings")

从 Preferences DataStore 读取内容

由于 Preferences DataStore 不使用预定义的架构,因此您必须使用相应的键类型函数为需要存储在 DataStore<Preferences> 实例中的每个值定义一个键。例如,如需为 int 值定义一个键,请使用 intPreferencesKey()。然后,使用 DataStore.data 属性,通过 Flow 提供适当的存储值。

val EXAMPLE_COUNTER = intPreferencesKey("example_counter")
val exampleCounterFlow: Flow<Int> = context.dataStore.data
 .map { preferences ->
 // No type safety.
 preferences[EXAMPLE_COUNTER] ?: 0
}

将内容写入 Preferences DataStore

suspend fun incrementCounter() {
 context.dataStore.edit { settings ->
 val currentCounterValue = settings[EXAMPLE_COUNTER] ?: 0
 settings[EXAMPLE_COUNTER] = currentCounterValue + 1
 }
}

使用 Proto DataStore 存储类型化的对象

Proto DataStore 实现使用 DataStore 和协议缓冲区将类型化的对象保留在磁盘上。

Proto DataStore 要求在 app/src/main/proto/ 目录的 proto 文件中保存预定义的架构。此架构用于定义您在 Proto DataStore 中保存的对象的类型。如需详细了解如何定义 proto 架构,请参阅 protobuf 语言指南。'

您的存储对象的类在编译时由 proto 文件中定义的 message 生成。请务必重新构建您的项目。

创建 Proto DataStore

  1. 定义一个实现 Serializer<T> 的类,其中 T 是 proto 文件中定义的类型。此序列化器类会告知 DataStore 如何读取和写入您的数据类型。请务必为该序列化器添加默认值,以便在尚未创建任何文件时使用。

  2. 使用由 dataStore 创建的属性委托来创建 DataStore<T> 的实例,其中 T 是在 proto 文件中定义的类型。在您的 Kotlin 文件顶层调用该实例一次,便可在应用的所有其余部分通过此属性委托访问该实例。filename 参数会告知 DataStore 使用哪个文件存储数据,而 serializer 参数会告知 DataStore 第 1 步中定义的序列化器类的名称。

object SettingsSerializer : Serializer<Settings> {
 override val defaultValue: Settings = Settings.getDefaultInstance()

 override suspend fun readFrom(input: InputStream): Settings {
 try {
 return Settings.parseFrom(input)
 } catch (exception: InvalidProtocolBufferException) {
 throw CorruptionException("Cannot read proto.", exception)
 }
 }

 override suspend fun writeTo(t: Settings,output: OutputStream) = t.writeTo(output)
}

val Context.settingsDataStore: DataStore<Settings> by dataStore(
 fileName = "settings.pb",
 serializer = SettingsSerializer
)

读取内容

val exampleCounterFlow: Flow<Int> = context.settingsDataStore.data
 .map { settings ->
 // The exampleCounter property is generated from the proto schema.
 settings.exampleCounter
 }

将内容写入 Proto DataStore

Proto DataStore 提供了一个 updateData() 函数,用于以事务方式更新存储的对象。updateData() 为您提供数据的当前状态,作为数据类型的一个实例,并在原子读-写-修改操作中以事务方式更新数据。

suspend fun incrementCounter() {
 context.settingsDataStore.updateData { currentSettings ->
 currentSettings.toBuilder()
 .setExampleCounter(currentSettings.exampleCounter + 1)
 .build()
 }
}

在同步代码中使用 DataStore

DataStore 的主要优势之一是异步 API,但可能不一定始终能将周围的代码更改为异步代码。如果您使用的现有代码库采用同步磁盘 I/O,或者您的依赖项不提供异步 API,就可能出现这种情况。

Kotlin 协程提供 runBlocking() 协程构建器,以帮助消除同步与异步代码之间的差异。您可以使用 runBlocking() 从 DataStore 同步读取数据。RxJava 在 Flowable 上提供阻塞方法。以下代码会阻塞发起调用的线程,直到 DataStore 返回数据:

val exampleData = runBlocking { context.dataStore.data.first() }

对界面线程执行同步 I/O 操作可能会导致 ANR 或界面卡顿。您可以通过从 DataStore 异步预加载数据来减少这些问题:

override fun onCreate(savedInstanceState: Bundle?) {
 lifecycleScope.launch {
 context.dataStore.data.first()
 // You should also handle IOExceptions here.
 }
}

这样,DataStore 可以异步读取数据并将其缓存在内存中。以后使用 runBlocking() 进行同步读取的速度可能会更快,或者如果初始读取已经完成,可能也可以完全避免磁盘 I/O 操作。

多进程中使用

这个功能在alpha1.1中支持,插个眼

相关文章

  • Jetpack DataStore详解

    DataStore出现的原因 Jetpack DataStore is a data storage soluti...

  • Jetpack DataStore

    Jetpack DataStore 是一种数据存储解决方案,允许您使用协议缓冲区[https://develope...

  • jetpack DataStore学习

    DataStore由来 Google 新增加了一个新 Jetpack 的成员 DataStore,主要用来替换 S...

  • Android Jetpack架构组件(十一)— DataSto

    一、DataStore简介 Jetpack DataStore 是一种数据存储解决方案,允许您使用协议缓冲区[ht...

  • Jetpack成员-DataStore

    DataStore 定义: 一种数据存储解决方案,允许您使用协议缓冲区[https://developers.go...

  • Android Jetpack DataStore

    导语 Jetpack简介及其它组件文章[https://www.jianshu.com/p/ac8d3340771...

  • DataStore 使用

    DataStore 是Jetpack 组件之一,是Google 开发出来用以代替SharedPreferences...

  • 2021-07-14

    Google 增加了一个新 Jetpack 的成员 DataStore,主要用来替换 SharedPreferen...

  • Jetpack Preferences DataStore 入门

    1. 简介 DataStore是Google Android Jetpack组件新推出的数据存储解决方案,其主要优...

  • DataStore

    Jetpack 的 DataStore 是一种数据存储解决方案,可以像 SharedPreferences 一样存...

网友评论

      本文标题:Jetpack DataStore

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