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

离线状态下显示Room数据库存储数据异常求助

问题:离线状态下Room数据库数据丢失,无法正常展示

我从自建API获取数据并存入Room数据库,但离线时数据库中的数据总是丢失,无法正常展示。我的需求如下:

  • 若离线但数据库中有数据,在RecyclerView中展示数据,同时播放按钮提示无网络;
  • 若离线且数据库中无数据,RecyclerView显示无数据。

网络状态检查代码

if (!isConnected){
    program.text = "Requires internet"
    //startTime.visibility = View.INVISIBLE
    //endTime.visibility = View.INVISIBLE
//            emptyString.visibility = View.VISIBLE
//            emptyString.text = "No internet"
    apiViewModel.programs.observe(this) {
            programs -> run {
        adapter.submitList(programs)
       // Log.d("Programs", "$programs")
    }
    }
    play.setOnClickListener {
        Toast.makeText(this, "Requires internet", Toast.LENGTH_SHORT).show()
    }
    stop.setOnClickListener {
        finish()
        stopService(Intent(this, BackgroundStreamService::class.java))
    }

} else{
    //startTime.visibility = View.VISIBLE
    //endTime.visibility = View.VISIBLE
    play.setOnClickListener {

        if(isPlaying){


            play.setImageResource(R.drawable.baseline_play_arrow_24)
            stopService(Intent(this, BackgroundStreamService::class.java))
            isPlaying = false


        }else{
            startForegroundService(Intent(this, BackgroundStreamService::class.java))
            isPlaying = true
            //play.setBackgroundResource(R.drawable.baseline_stop_24)
            play.setImageResource(R.drawable.baseline_stop_24)
        }


    }

    stop.setOnClickListener {

        finish()
        stopService(Intent(this, BackgroundStreamService::class.java))

    }
    //fetchPrograms()
    apiViewModel.programs.observe(this) {
            programs -> run {
        adapter.submitList(programs)
        Log.d("Programs", "$programs")
    }
}

}

Repo代码

val programs: LiveData<List<Program>> = Transformations.map(programDao.getPrograms()){
    it.asDomainModel()
}
suspend fun refreshPrograms(){
    withContext(Dispatchers.IO){
        val programs = NodejsApi.programApi.getProgramAsync().await()
        programDao.insertAll(programs)
    }
}

问题排查及解决建议

  1. 统一LiveData观察逻辑
    目前代码在网络状态分支中分别设置programs的观察者,容易导致重复观察或观察时机错误。建议将观察者移到网络判断外部,只初始化一次:

    // 移到onCreate或合适的初始化位置,只调用一次
    apiViewModel.programs.observe(this) { programs ->
        adapter.submitList(programs)
        // 处理空数据状态
        if (programs.isEmpty()) {
            emptyString.visibility = View.VISIBLE
            emptyString.text = if (!isConnected) "无数据" else ""
        } else {
            emptyString.visibility = View.GONE
        }
    }
    
    // 后续只处理网络状态对应的UI逻辑
    if (!isConnected) {
        program.text = "需要网络"
        play.setOnClickListener {
            Toast.makeText(this, "需要网络", Toast.LENGTH_SHORT).show()
        }
        // ...其他离线逻辑
    } else {
        // ...在线逻辑
    }
    
  2. 检查数据插入与查询逻辑

    • 确认programDao.insertAll的注解是否正确,若使用@Insert(onConflict = OnConflictStrategy.REPLACE),需确保在线刷新时不会误删已有数据;若要保留旧数据,可改用OnConflictStrategy.IGNORE。
    • 检查programDao.getPrograms()是否返回数据库中所有数据,避免查询条件错误导致数据无法被获取。
    • 验证asDomainModel()转换方法,确保实体类到领域模型的字段映射完全正确,没有遗漏或错误转换。
  3. 确认数据是否真正存入数据库
    在refreshPrograms()中添加日志,确认API返回的数据不为空,且插入数据库操作成功:

    suspend fun refreshPrograms(){
        withContext(Dispatchers.IO){
            val programs = NodejsApi.programApi.getProgramAsync().await()
            Log.d("Repo", "API返回数据:${programs.size}条")
            programDao.insertAll(programs)
            // 插入后查询一次,确认数据存在
            val dbData = programDao.getPrograms().value
            Log.d("Repo", "数据库当前数据:${dbData?.size ?: 0}条")
        }
    }
    
  4. 检查Room数据库配置

    • 确保数据库实例是单例模式,避免多个实例导致数据不一致。
    • 若进行过数据库版本升级,检查迁移逻辑是否正确,错误的迁移可能导致数据丢失。
  5. 完善离线状态的UI处理
    按照需求,离线时:

    • 数据库有数据:展示RecyclerView,播放按钮点击提示无网络;
    • 数据库无数据:显示无数据提示。
      这部分逻辑可以放在programs的观察者中结合网络状态判断实现,如第一步的示例代码。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 05:53:19