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

Database Inspector添加Room数据后App无法显示且提示无法访问离线数据库

问题描述
  • 通过Android Studio的App Inspector向Room数据库添加数据,查询执行成功,但App启动后以LazyColumn展示的数据库条目无法显示
  • 使用Database Inspector添加数据成功,但App内无展示,同时出现「cannot access offline database」错误

相关代码

Entity

package com.example.taskmaster.data.models

import androidx.room.Entity
import androidx.room.PrimaryKey
import com.example.taskmaster.utils.Constants.Database_Table

@Entity(tableName = Database_Table)
data class Tasks(
    @PrimaryKey(autoGenerate = true)
    val id: Int = 0,
    val title: String,
    val description: String,
    val priority: Priority
)

Database

package com.example.taskmaster.data

import androidx.room.Database
import androidx.room.RoomDatabase
import com.example.taskmaster.data.models.Tasks

@Database(entities = [Tasks::class], version = 1)
abstract class TaskmasterDatabase : RoomDatabase() {
    abstract fun tasksDao(): TasksDao
}

Dao

package com.example.taskmaster.data

import androidx.room.Dao
import androidx.room.Delete
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
import androidx.room.Update
import com.example.taskmaster.data.models.Tasks
import kotlinx.coroutines.flow.Flow

@Dao
interface TasksDao {

    @Query("SELECT * FROM Tasks_table ORDER BY id ASC")
    fun GetAllTasks(): Flow<List<Tasks>>

    @Query("SELECT * FROM Tasks_Table WHERE id=:tid")
    fun GetSelectedTask(tid: Int): Flow<Tasks>

    @Insert(onConflict = OnConflictStrategy.IGNORE)
    suspend fun AddTask(task: Tasks)

    @Delete
    suspend fun DeleteTask(task: Tasks)

    @Update
    suspend fun UpdateTask(task: Tasks)

    @Query("DELETE FROM Tasks_Table")
    suspend fun DeleteAllTasks()

    @Query("SELECT * FROM Tasks_Table WHERE title like :searchQuery OR description like :searchQuery")
    fun searchDatabase(searchQuery: String): Flow<List<Tasks>>

    @Query("SELECT * FROM Tasks_Table ORDER BY CASE WHEN priority LIKE 'L%' THEN 1 WHEN priority like 'M%' THEN 2 WHEN priority LIKE 'H%' THEN 3 END")
    fun sortTasksLow(): Flow<List<Tasks>>

    @Query("SELECT * FROM Tasks_Table ORDER BY CASE WHEN priority LIKE 'H%' THEN 1 WHEN priority like 'M%' THEN 2 WHEN priority LIKE 'L%' THEN 3 END")
    fun sortTasksHigh(): Flow<List<Tasks>>
}

ViewModel

package com.example.taskmaster.ui.viewmodels

import androidx.compose.runtime.MutableState
import androidx.compose.runtime.mutableStateOf
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.example.taskmaster.data.models.Tasks
import com.example.taskmaster.data.repositories.TaskmasterRepository
import com.example.taskmaster.utils.RequestState
import com.example.taskmaster.utils.SearchAppBarState
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.launch
import javax.inject.Inject

@HiltViewModel
class SharedViewModel @Inject constructor(
    private val repository: TaskmasterRepository
) : ViewModel() {
    val searchAppBarState: MutableState<SearchAppBarState> = mutableStateOf(SearchAppBarState.CLOSED)
    val searchTextState: MutableState<String> = mutableStateOf("")

    private val _alltasks: MutableStateFlow<RequestState<List<Tasks>>> = MutableStateFlow(RequestState.Idle)
    val alltasks: StateFlow<RequestState<List<Tasks>>> = _alltasks

    fun getalltasks() {
        _alltasks.value = RequestState.Loading
        try {
            viewModelScope.launch {
                repository.getAllTasks.collect {
                    _alltasks.value = RequestState.Success(it)
                }
            }
        } catch (e: Exception) {
            _alltasks.value = RequestState.Error(e)
        }
    }
}

界面说明

  • App启动时界面:LazyColumn区域空白无数据
  • 错误界面:显示「cannot access offline database」提示
解决方案

1. 修复数据库连接与持久化问题

「cannot access offline database」错误通常是Database Inspector与App数据库实例不匹配导致的,需确保:

  • 数据库创建使用Room.databaseBuilder而非内存模式:
// Hilt数据库模块示例
@Module
@InstallIn(SingletonComponent::class)
object DatabaseModule {
    @Provides
    @Singleton
    fun provideDatabase(@ApplicationContext context: Context): TaskmasterDatabase {
        return Room.databaseBuilder(
            context,
            TaskmasterDatabase::class.java,
            "taskmaster_db"
        )
            .fallbackToDestructiveMigration() // 测试阶段允许销毁重建数据库
            .build()
    }

    @Provides
    fun provideTasksDao(database: TaskmasterDatabase): TasksDao {
        return database.tasksDao()
    }
}
  • 仅在Debug模式下运行App,Release模式下Database Inspector无法访问数据库
  • 检查Database Inspector中选中的进程与当前运行App一致

2. 统一Dao表名并修正方法命名

Dao中存在表名大小写不一致(Tasks_table/Tasks_Table),统一使用常量避免错误:

// Dao中修改查询语句
@Query("SELECT * FROM ${Database_Table} ORDER BY id ASC")
fun getAllTasks(): Flow<List<Tasks>> // 方法名改为小写开头,符合Kotlin规范

3. 添加Priority枚举类型转换器

Entity中使用了Priority枚举,但未提供类型转换逻辑,Room无法直接存储枚举,需添加转换器:

// 定义枚举与转换器
enum class Priority { LOW, MEDIUM, HIGH }

class PriorityConverter {
    @TypeConverter
    fun fromPriority(priority: Priority): String = priority.name

    @TypeConverter
    fun toPriority(priorityString: String): Priority = Priority.valueOf(priorityString)
}

// 在Database类中注册转换器
@Database(entities = [Tasks::class], version = 1)
@TypeConverters(PriorityConverter::class)
abstract class TaskmasterDatabase : RoomDatabase() {
    abstract fun tasksDao(): TasksDao
}

4. 确保ViewModel数据加载方法被调用

在Compose界面初始化时调用getalltasks(),并正确收集Flow状态:

@Composable
fun TaskListScreen(viewModel: SharedViewModel = hiltViewModel()) {
    // 界面启动时触发数据加载
    LaunchedEffect(key1 = true) {
        viewModel.getalltasks()
    }

    val tasksState = viewModel.alltasks.collectAsState()

    when (val state = tasksState.value) {
        is RequestState.Success -> {
            LazyColumn {
                items(state.data) { task ->
                    // 渲染单个任务项
                    TaskItem(task = task)
                }
            }
        }
        is RequestState.Loading -> CircularProgressIndicator()
        is RequestState.Error -> Text(text = "加载失败:${state.exception.message}")
        RequestState.Idle -> Unit
    }
}

5. 验证数据库文件一致性

通过代码打印数据库文件路径,确认Database Inspector连接的是同一个文件:

// 在Activity或ViewModel中打印路径
val dbPath = context.getDatabasePath("taskmaster_db").absolutePath
Log.d("DB_PATH", dbPath)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 10:09:51