You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Kotlin+Jetpack Compose:点击Done按钮多次才能向Room数据库插入数据

Room数据库需多次点击才插入数据的问题排查与修复

问题核心原因

你的问题出在状态更新的时序异步性:在点击事件中连续调用setNoOfQuestions、setQuestionsSolved、upsertQuestionsSolved时,ViewModel的uiState状态更新不会立即同步。导致:

  • 调用setQuestionsSolved时,uiState.noOfQuestions还是旧值,并未使用刚传入的it
  • 最终upsert的uiState.questionsSolved是未更新的无效数据
  • 多次点击后状态逐步同步,直到第三次才凑齐正确数据完成插入

修复方案

将状态更新与数据库插入逻辑合并到ViewModel内部,避免在外部依赖未同步的uiState值:

1. 在ViewModel中新增统一处理函数

fun onDoneClicked(newNoOfQuestions: Int) {
    viewModelScope.launch {
        // 1. 更新UI状态中的题目数量
        _uiState.update { currentState ->
            currentState.copy(noOfQuestions = newNoOfQuestions)
        }
        // 2. 创建/更新要插入的QuestionsSolved对象(直接用最新状态值)
        val updatedData = uiState.value.questionsSolved.copy(
            date = uiState.value.date,
            noOfQuestions = newNoOfQuestions
        )
        // 3. 执行数据库插入
        dao.upsertQuestionsSolved(updatedData)
        // 4. 更新UI状态中的questionsSolved
        _uiState.update { currentState ->
            currentState.copy(questionsSolved = updatedData)
        }
    }
}

(注:若你使用mutableStateOf而非MutableStateFlow,将_uiState.update改为直接赋值即可)

2. 简化Done按钮的点击逻辑

Button(
    onClick = {
        viewModel.onDoneClicked(textState.toInt())
    }
) {
    Text(text = "Done")
}

3. 移除分散的状态调用

删除原点击事件中的setNoOfQuestions、setQuestionsSolved、upsertQuestionsSolved独立调用,所有逻辑通过onDoneClicked统一处理,确保每一步都使用最新状态值。

额外检查点

  • 确认QuestionsSolved的主键配置:若@Upsert的主键值(比如日期)未变化,Room会执行更新而非插入,可能造成“未插入”的错觉
  • 若使用mutableStateOf,确保状态更新在viewModelScope内执行,保证线程安全

内容的提问来源于stack exchange,提问作者Chitin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 16:25:04