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


相关推荐
alexhilton1 天前
使用FunctionGemma进行设备端函数调用
android·kotlin·android jetpack
冬奇Lab1 天前
InputManagerService:输入事件分发与ANR机制
android·源码阅读
张小潇2 天前
AOSP15 Input专题InputManager源码分析
android·操作系统
RdoZam2 天前
Android-封装基类Activity\Fragment,从0到1记录
android·kotlin
奥陌陌2 天前
android 打印函数调用堆栈
android
用户985120035832 天前
Compose Navigation 3 深度解析(二):基础用法
android·android jetpack
恋猫de小郭2 天前
Android 官方正式官宣 AI 支持 AppFunctions ,Android 官方 MCP 和系统级 OpenClaw 雏形
android·前端·flutter
黄林晴2 天前
Android 17 Beta 2,隐私这把锁又拧紧了
android
Kapaseker2 天前
研究表明,开发者对Kotlin集合的了解不到 20%
android·kotlin
bqliang2 天前
Compose 媒体查询 (Media Query API) 🖱️👇🕹️
android·android jetpack