Android DataStore详解

1. 为什么选择DataStore?

1.1 背景

在Android开发中,SharedPreferences 一直是轻量级存储键值对的常用工具。然而,随着应用的复杂性增加,SharedPreferences 的一些局限性逐渐显现:

  • 性能问题:在主线程进行 I/O 操作,可能导致 UI 卡顿。
  • 缺乏类型安全:需要手动进行类型转换,容易出错。
  • 事务冲突:多个线程同时写入时可能出现数据覆盖问题。
  • 同步问题apply() 方法是异步的,不能保证数据立即持久化。

为了解决这些问题,Google 在 Jetpack 中引入了 DataStore,它采用了更现代化的设计,提供了更高效和安全的数据存储方案。

1.2 DataStore 的特点

  • 异步非阻塞:基于 Kotlin 协程,所有操作均为异步,避免阻塞主线程。
  • 类型安全:支持 Preferences DataStoreProto DataStore 两种类型,后者提供了更严格的类型检查。
  • 更好的性能:基于文件流的底层实现,比 SharedPreferences 更高效。

2. DataStore 的两种类型

2.1 Preferences DataStore

存储键值对数据,类似于 SharedPreferences。适用于简单的数据存储场景。

2.2 Proto DataStore

基于 Protocol Buffers(Protobuf),用于存储结构化数据。适合需要严格类型的数据模型。


3. 与 SharedPreferences 的区别

特性SharedPreferencesDataStore
存储方式基于 XML 文件基于文件流
异步支持不完全异步,apply 异步,commit 同步完全异步
线程安全存在并发问题原生线程安全
类型安全不支持,需要手动管理Proto DataStore 支持严格类型安全
性能主线程阻塞风险高效,非阻塞

4. 如何使用 DataStore

4.1 添加依赖

build.gradle 文件中添加:

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

4.2 Preferences DataStore 示例

4.2.1 初始化 DataStore
val Context.dataStore: DataStore<Preferences> by preferencesDataStore(name = "settings")
4.2.2 写入数据
suspend fun saveSetting(context: Context, key: String, value: Int) {
    val dataStoreKey = intPreferencesKey(key)
    context.dataStore.edit { settings ->
        settings[dataStoreKey] = value
    }
}
4.2.3 读取数据
val exampleFlow: Flow<Int> = context.dataStore.data
    .map { preferences ->
        preferences[intPreferencesKey("example_key")] ?: 0
    }

4.3 Proto DataStore 示例

4.3.1 定义 Protobuf 文件

创建 settings.proto 文件:

syntax = "proto3";
option java_package = "com.example.datastore";
option java_outer_classname = "SettingsProto";

message Settings {
    int32 example_value = 1;
}

编译生成对应的类文件。

4.3.2 初始化 Proto DataStore
val Context.protoDataStore: DataStore<Settings> by dataStore(
    fileName = "settings.pb",
    serializer = SettingsSerializer
)
4.3.3 创建序列化器
object SettingsSerializer : Serializer<Settings> {
    override val defaultValue: Settings = Settings.getDefaultInstance()

    override suspend fun readFrom(input: InputStream): Settings {
        return try {
            Settings.parseFrom(input)
        } catch (exception: InvalidProtocolBufferException) {
            defaultValue
        }
    }

    override suspend fun writeTo(t: Settings, output: OutputStream) {
        t.writeTo(output)
    }
}
4.3.4 写入数据
suspend fun updateExampleValue(context: Context, value: Int) {
    context.protoDataStore.updateData { settings ->
        settings.toBuilder().setExampleValue(value).build()
    }
}
4.3.5 读取数据
val exampleValueFlow: Flow<Int> = context.protoDataStore.data
    .map { settings ->
        settings.exampleValue
    }

5. 图解 DataStore 工作原理

6. 总结

DataStore 是 Android 平台上对标 SharedPreferences 的现代化存储解决方案。通过支持异步、类型安全和更高效的底层实现,DataStore 提供了一种更适合现代应用的数据存储方式。开发者可以根据具体需求选择 Preferences DataStoreProto DataStore 来满足应用需求。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Vincent(朱志强)

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值