DataStore基本使用教程

Android DataStore(Preferences)基本使用教程

1. DataStore 是什么?

DataStore 是 Android 官方提供的数据持久化方案 ,用于存储小规模本地数据

SharedPreferences 的推荐替代方案

核心特性:

  • 基于 Kotlin Coroutines + Flow
  • 线程安全
  • 原子写入
  • 支持 数据变化监听
  • 官方长期维护

2. DataStore 的两种类型(先分清)

类型 依赖 使用场景
Preferences DataStore androidx.datastore:datastore-preferences Key-Value,替代 SharedPreferences
Proto DataStore androidx.datastore:datastore 强类型对象,复杂数据

👉 本文只讲 Preferences DataStore


3. 添加依赖

3.1 使用 Version Catalog(推荐)

toml 复制代码
[libraries]
androidx-datastore-preferences = { 
    module = "androidx.datastore:datastore-preferences", 
    version = "1.1.0" 
}
kotlin 复制代码
implementation(libs.androidx.datastore.preferences)

3.2 直接依赖(不推荐但可用)

kotlin 复制代码
implementation("androidx.datastore:datastore-preferences:1.1.0")

4. 定义 DataStore(关键)

4.1 在 Context 上定义(必须是单例)

kotlin 复制代码
val Context.dataStore by preferencesDataStore(
    name = "settings"
)

📌 规则:

  • 一个文件 = 一个 DataStore
  • 不要在多个地方重复定义
  • 通常放在 Applicationdatastore 包中

5. 定义 Key(强烈建议集中管理)

kotlin 复制代码
object PreferenceKeys {
    val MUSIC_ID = stringPreferencesKey("music_id")
    val POSITION = longPreferencesKey("position")
    val IS_PLAYING = booleanPreferencesKey("is_playing")
}

支持的类型:

  • stringPreferencesKey
  • intPreferencesKey
  • longPreferencesKey
  • booleanPreferencesKey
  • floatPreferencesKey
  • stringSetPreferencesKey

6. 写数据(edit)

6.1 基本写法

kotlin 复制代码
suspend fun saveMusicId(context: Context, id: String) {
    context.dataStore.edit { prefs ->
        prefs[PreferenceKeys.MUSIC_ID] = id
    }
}

特点

  • editsuspend 函数
  • 自动切换线程(不会阻塞主线程)
  • 一次 edit 是一个原子事务

6.2 一次写多个值(推荐)

kotlin 复制代码
context.dataStore.edit { prefs ->
    prefs[PreferenceKeys.MUSIC_ID] = "123"
    prefs[PreferenceKeys.POSITION] = 1000L
}

✔ 要么全部成功

✔ 要么全部失败


7. 读数据(Flow)

7.1 基本读取

kotlin 复制代码
val musicIdFlow: Flow<String> =
    context.dataStore.data
        .map { prefs ->
            prefs[PreferenceKeys.MUSIC_ID] ?: ""
        }

特点

  • 返回的是 Flow
  • 数据变化会自动 emit
  • 不需要回调

7.2 一次读多个值(推荐)

kotlin 复制代码
data class PlayerState(
    val musicId: String,
    val position: Long
)

val playerStateFlow: Flow<PlayerState> =
    context.dataStore.data.map { prefs ->
        PlayerState(
            musicId = prefs[PreferenceKeys.MUSIC_ID] ?: "",
            position = prefs[PreferenceKeys.POSITION] ?: 0L
        )
    }

8. 在 ViewModel 中使用(推荐)

kotlin 复制代码
class PlayerViewModel(
    private val context: Context
) : ViewModel() {

    val playerState = context.dataStore.data
        .map { prefs ->
            prefs[PreferenceKeys.MUSIC_ID] ?: ""
        }
}

9. 在 Compose 中使用(最佳实践)

kotlin 复制代码
@Composable
fun PlayerScreen(viewModel: PlayerViewModel) {
    val musicId by viewModel.playerState
        .collectAsStateWithLifecycle(initialValue = "")

    Text(text = musicId)
}

10. 清除数据

10.1 清空全部

kotlin 复制代码
context.dataStore.edit { it.clear() }

10.2 删除某个 key

kotlin 复制代码
context.dataStore.edit { prefs ->
    prefs.remove(PreferenceKeys.MUSIC_ID)
}

11. 与 SharedPreferences 的对比

对比项 SharedPreferences DataStore
线程安全
写入方式 同步 / apply 协程
原子性
数据监听 Flow
官方推荐

12. 常见错误(必须注意)

❌ 1. 把 DataStore 当数据库用

  • 不适合大量数据
  • 不适合高频写入

❌ 2. 每次都新建 DataStore

kotlin 复制代码
preferencesDataStore(...) // ❌ 多次调用

👉 必须是单例


❌ 3. 在主线程调用 .first()

kotlin 复制代码
dataStore.data.first() // ❌ 可能阻塞

👉 应在 Dispatchers.IO 或协程中调用


❌ 4. 存复杂对象

Preferences DataStore 不支持对象

👉 复杂结构请使用 Proto DataStore


13. 什么时候不该用 DataStore?

❌ 大量数据

❌ 高频实时数据(如 1 秒一次进度)

❌ 复杂关系型数据

👉 这些场景请用:

  • Room
  • 文件
  • 数据库

14. 最佳实践总结(工程级)

  • 一个 DataStore 一个文件
  • Key 集中管理
  • edit 中一次写完
  • Flow + ViewModel + Compose
  • 高频数据做节流 / 阈值写

15. 一句话总结

DataStore Preferences = 线程安全 + 原子写入 + Flow 化的 SharedPreferences


相关推荐
LawrenceMssss3 小时前
由于创建一个完整的App涉及到多个层面(如前端、后端、数据库等),并且每种语言通常有其特定的用途(如Java/Kotlin用于Android开发,Swift/Objective-C用于iOS开发,Py
android·java·ios
chen_mangoo3 小时前
HDMI简介
android·linux·驱动开发·单片机·嵌入式硬件
阿里-于怀3 小时前
AgentScope AutoContextMemory:告别 Agent 上下文焦虑
android·java·数据库·agentscope
Larry_Yanan4 小时前
Qt安卓开发(三)双摄像头内嵌布局
android·开发语言·c++·qt·ui
粲然忧生4 小时前
腾讯云终端性能监控SDK正式上线,为鸿蒙开发适配保驾护航
android·腾讯云·harmonyos
我命由我123454 小时前
Kotlin 开发 - Kotlin Lambda 表达式返回值
android·java·开发语言·java-ee·kotlin·android studio·android-studio
FrameNotWork4 小时前
Android Camera HAL实现windows摄像头显示:从黑屏到彩色照片的完整攻坚
android
PyHaVolask6 小时前
CSRF跨站请求伪造
android·前端·csrf