Blog
首页
文档
收藏
关于
  • 在线转换时间戳 (opens new window)
  • 在线压缩图片 (opens new window)
  • Float-Double转二进制 (opens new window)
  • 文件转Hex字符串 (opens new window)

HiuZing

🍑
首页
文档
收藏
关于
  • 在线转换时间戳 (opens new window)
  • 在线压缩图片 (opens new window)
  • Float-Double转二进制 (opens new window)
  • 文件转Hex字符串 (opens new window)
  • 拉取安卓设备文件
  • permission
  • 常用命令
  • Android入门
  • Compose
  • MVVM架构
  • 网络请求
  • 数据持久化
    • DataStore
      • 文件结构
      • DataStore VS SharedPreferences
      • 读取数据
      • 更新数据
    • Room
      • DataStore VS Room
      • 文件结构
  • Android
HiuZing
2026-10-06
目录

数据持久化

# DataStore

# 文件结构

app/src/main/java/com/taobao/interview_tong_ad/
├── MainActivity.kt              ← 修改:初始化 SettingsManager
├── data/
│   ├── local/
│   │   └── TodoPreferences.kt   ← 新建:DataStore 存取(第5、6步)
│   └── model/
│       └── TodoModels.kt        ← 新建:TodoItem 数据模型(第1步)
├── ui/
│   ├── pages/
│   │   └── TodoScreen.kt        ← 新建:UI 页面(第1步,第8步改造)
│   └── viewmodel/
│       └── TodoViewModel.kt     ← 新建:ViewModel(第7步)
└── utils/
    └── SettingsManager.kt       ← 新建:全局状态管理(第二节第2步)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
文件 第一节/第二节 作用
TodoModels.kt 第1步创建 TodoItem数据模型 + @Serializable
TodoScreen.kt 第1步创建,第8步改造 UI 页面
TodoPreferences.kt 第5、6步创建 DataStore 读写
TodoViewModel.kt 第7步创建 管理状态 + 调用 Preferences
SettingsManager.kt 第二节第2步创建 全局昵称管理(对应 AuthManager)
MainActivity.kt 修改已有文件 App 启动时初始化

TodoModels.kt

// 数据模型
data class TodoItem(
    val id: String = UUID.randomUUID().toString(),
    val text: String,
    val isDone: Boolean = false
)
1
2
3
4
5
6

TodoScreen.kt

// 样式
fun TodoScreen(viewModel: TodoViewModel = viewModel()) {
    val todos by viewModel.todos.collectAsState()  // ← 从 ViewModel 获取状态
    var inputText by remember { mutableStateOf("") }
1
2
3
4

TodoPreferences.kt

import androidx.datastore.core.DataStore
import androidx.datastore.preferences.core.*
import androidx.datastore.preferences.preferencesDataStore

// 顶层声明,确保全局只有一个 DataStore 实例
private val Context.dataStore: DataStore<Preferences> by preferencesDataStore(name = "todo_store")

// 传入Context实例
class TodoPreferences(context: Context) {
    private val dataStore = context.dataStore

    // JSON 解析器(第8讲学的)
    private val json = Json { ignoreUnknownKeys = true }

    // 定义 Key:存 JSON 字符串
    private val TODO_KEY = stringPreferencesKey("todo_list")

    /** 保存待办列表 → 序列化成 JSON → 存入 DataStore */
    suspend fun saveTodos(todos: List<TodoItem>) {
        val jsonStr = json.encodeToString(ListSerializer(TodoItem.serializer()), todos)
        dataStore.edit { it[TODO_KEY] = jsonStr }
    }

    /** 从 DataStore 读取 JSON → 反序列化成 List<TodoItem> */
    suspend fun loadTodos(): List<TodoItem> {
        return dataStore.data.map { prefs ->
            val jsonStr = prefs[TODO_KEY] ?: ""
            if (jsonStr.isEmpty()) emptyList()
            else json.decodeFromString(ListSerializer(TodoItem.serializer()), jsonStr)
        }.first()
    }
    
    
    // 新增:昵称的 Key
    private val NICKNAME_KEY = stringPreferencesKey("nickname")

    /** 保存昵称 */
    suspend fun saveNickname(name: String) {
        dataStore.edit { it[NICKNAME_KEY] = name }
    }

    /** 读取昵称 */
    suspend fun loadNickname(): String {
        return dataStore.data.map { it[NICKNAME_KEY] ?: "" }.first()
    }
    
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47

TodoViewModel.kt

// 管理数据
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import androidx.lifecycle.viewmodel.compose.viewModel

class TodoViewModel(application: Application) : AndroidViewModel(application) {
    // UI 状态:待办列表(第7讲学的 StateFlow)
    private val _todos = MutableStateFlow<List<TodoItem>>(emptyList())
    val todos = _todos.asStateFlow()

    // DataStore 操作类
    private val preferences = TodoPreferences(application)

    init {
        // App 启动时从 DataStore 加载待办列表
        viewModelScope.launch {
            _todos.value = preferences.loadTodos()
        }
    }

    /** 保存到 DataStore */
    private fun saveToDataStore(todos: List<TodoItem>) {
        viewModelScope.launch {
            preferences.saveTodos(todos)
        }
    }

    /** 添加待办 */
    fun addTodo(text: String) {
        val newTodo = TodoItem(text = text)
        val updated = _todos.value + newTodo
        _todos.value = updated
        saveToDataStore(updated)
    }

    /** 切换完成状态 */
    fun toggleTodo(id: String) {
        val updated = _todos.value.map {
            if (it.id == id) it.copy(isDone = !it.isDone) else it
        }
        _todos.value = updated
        saveToDataStore(updated)
    }

    /** 删除待办 */
    fun deleteTodo(id: String) {
        val updated = _todos.value.filter { it.id != id }
        _todos.value = updated
        saveToDataStore(updated)
    }
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

SettingsManager.kt

// 全局使用(单例模式)用 object 单例 + StateFlow + DataStore
// APP启动的时候初始化

import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow

object SettingsManager {
    // 全局可观察的昵称状态(第7讲学的 StateFlow)
    private val _nickname = MutableStateFlow("")
    val nickname = _nickname.asStateFlow()

    private var preferences: TodoPreferences? = null

    /** 初始化 - 从本地加载昵称(App 启动时调用) */
    suspend fun init(context: Context) {
        // 1. 创建 TodoPreferences
        preferences = TodoPreferences(context.applicationContext)

        // 2. 从 DataStore 读取保存的昵称
        _nickname.value = preferences!!.loadNickname()
    }

    /** 设置昵称(保存到内存 + DataStore) */
    suspend fun setNickname(name: String) {
        // 1. 更新内存中的状态(UI 自动刷新)
        _nickname.value = name

        // 2. 持久化到 DataStore(App 重启后恢复)
        preferences?.saveNickname(name)
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

MainActivity.kt

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        // 初始化 SettingsManager(从本地加载昵称)
        // 传入上下文 this@MainActivity
        runBlocking {
            SettingsManager.init(this@MainActivity)
        }

        setContent {
            InterviewTongTheme {
                TodoScreen()
            }
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

# DataStore VS SharedPreferences

特性 DataStore(推荐) SharedPreferences(旧)
异步 协程 Flow(不阻塞主线程) 同步阻塞
线程安全 是 否
类型安全 PreferencesKey 字符串 Key
响应式 Flow 自动通知变化 需要手动刷新

全局唯一,用顶层委托创建

import androidx.datastore.core.DataStore
import androidx.datastore.preferences.core.*
import androidx.datastore.preferences.preferencesDataStore

// 顶层声明,确保全局只有一个 DataStore 实例
private val Context.dataStore: DataStore<Preferences> by preferencesDataStore(name = "todo_store")
1
2
3
4
5
6
代码 / 表达式 含义说明
by preferencesDataStore(name = "todo_store") 委托创建单例 DataStore
name = "todo_store" 存储文件名,数据保存在 todo_store.preferences_pb 文件中
Context 上下文
Context.dataStore 添加一个扩展属性,任何有 Context 的地方都能通过 context.dataStore 访问

# 读取数据

# 更新数据

# Room

# DataStore VS Room

特性 DataStore Room
数据类型 键值对(简单类型 + JSON 字符串) 关系型(表、行、列)
查询能力 只能按 Key 读取 支持 SQL 查询、排序、条件过滤
数据量 少量数据(配置、Token) 大量数据(聊天记录、文章列表)
复杂关系 不支持 支持多表关联
学习成本 低 中等(需学 SQL + 注解)
面试通适用 ✅ 用户信息、搜索历史 不需要(数据量小)

# 文件结构

app/src/main/java/com/taobao/interview_tong_ad/
├── data/local/
│   ├── TodoEntity.kt         ← @Entity:定义表
│   ├── TodoDao.kt            ← @Dao:定义增删改查
│   └── TodoDatabase.kt       ← @Database:数据库入口
└── ui/viewmodel/
    └── TodoRoomViewModel.kt  ← 用 Room 替代 DataStore
1
2
3
4
5
6
7
文件名 作用 步骤
build.gradle.kts + libs.versions.toml 添加 Room 依赖 第1步
TodoEntity.kt 定义 Entity — 数据表 第2步
TodoDao.kt 定义 Dao — 增删改查 第3步
TodoDatabase.kt 定义 Database — 数据库入口 第4步
TodoRoomViewModel.kt 创建 ViewModel— 用 Room 替代 DataStore 第5步

TodoEntity.kt

TodoDao.kt

TodoDatabase.kt

上次更新: 2026/10/07, 07:27:34
网络请求

← 网络请求

最近更新
01
02
网络请求
10-04
03
MVVM架构
10-03
更多文章>
Theme by Vdoing | Copyright © 2021-2026 WeiXiaojing | 友情链接
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式