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

Kotlin+SQLite安卓应用读取表记录返回空列表问题求助

安卓Room数据库预插入数据在应用内无法读取的问题排查与解决

问题描述

开发安卓答题应用时,通过SQLite预先插入了12条默认记录,在SQLite工具中可正常查询到这些数据,但应用内ViewModel返回的列表为空。通过Inspector确认表存在但无数据,数据库访问无异常。相关代码如下:

Dao接口

@Dao
interface QuizDao {
    @Query("SELECT * FROM quiz WHERE difficulty = :selectedDifficulty")
    fun loadQuiz(selectedDifficulty : String) : List<Quiz>
}

Database类

@Database(entities = [Quiz::class] , version = 1)
abstract class QuizDatabase : RoomDatabase(){
    abstract fun getQuizDao() : QuizDao
}

Repository类

class QuizRepository(var qdao: QuizDao) {
     fun loadQuestions(difficulty: String): List<Quiz> = qdao.loadQuiz(difficulty)
}

ViewModel类

@HiltViewModel
class GameViewModel @Inject constructor(var quizRepository: QuizRepository) : ViewModel() {
    val quizList = MutableLiveData<List<Quiz>>()

    init {
        loadAllQuestion()
    }

    private fun loadAllQuestion(){
        CoroutineScope(Dispatchers.Main).launch {
            quizList.value = quizRepository.loadQuestions("Easy")
        }
    }
}

Fragment代码

viewModel.quizList.observe(viewLifecycleOwner) {
    if (it.isNotEmpty()){
        selectedQuestions = it.shuffled().take(10)
        displayCurrentQuestion()
    } else {
        Log.e("tag","Empty")
    }
}

目前Fragment中观察到列表为空,输出"Empty"日志。


核心问题分析

应用内访问的数据库与SQLite工具查看的并非同一个文件,导致预插入的数据未加载到应用实际使用的数据库中;同时存在数据库操作线程违规的潜在问题。

排查与修复步骤

1. 确认数据库文件路径一致性

Room默认数据库存储路径为/data/data/[你的包名]/databases/,你用SQLite工具查看的可能是外部文件(如手动复制的测试文件、assets目录未正确拷贝的源文件)。可通过代码打印路径验证:

val dbPath = quizDatabase.openHelper.writableDatabase.path
Log.d("DB_PATH", dbPath)

对比该路径与工具查看的路径是否一致。

2. 修复预插入数据的拷贝逻辑

若通过assets目录下的数据库文件拷贝到应用目录,需确保拷贝逻辑在数据库创建时执行,使用RoomDatabase.Callback实现:

@Database(entities = [Quiz::class], version = 1)
abstract class QuizDatabase : RoomDatabase() {
    abstract fun getQuizDao(): QuizDao

    companion object {
        fun getInstance(context: Context): QuizDatabase {
            return Room.databaseBuilder(context, QuizDatabase::class.java, "quiz.db")
                .addCallback(object : Callback() {
                    override fun onCreate(db: SupportSQLiteDatabase) {
                        super.onCreate(db)
                        copyDatabaseFromAssets(context)
                    }
                })
                .build()
        }

        private fun copyDatabaseFromAssets(context: Context) {
            val inputStream = context.assets.open("quiz.db")
            val outputFile = context.getDatabasePath("quiz.db")
            val outputStream = FileOutputStream(outputFile)

            val buffer = ByteArray(1024)
            var length: Int
            while (inputStream.read(buffer).also { length = it } > 0) {
                outputStream.write(buffer, 0, length)
            }

            outputStream.flush()
            outputStream.close()
            inputStream.close()
        }
    }
}

注意:若数据库已创建过,onCreate不会重复执行,需卸载应用重装,或改用onOpen回调(需添加重复拷贝判断逻辑)。

3. 修正数据库操作线程问题

Room默认禁止在主线程执行数据库操作,原代码同步调用DAO方法会导致静默失败,需改为挂起函数配合协程:

  • 修改DAO为挂起函数:
@Dao
interface QuizDao {
    @Query("SELECT * FROM quiz WHERE difficulty = :selectedDifficulty")
    suspend fun loadQuiz(selectedDifficulty: String): List<Quiz>
}
  • Repository同步改为挂起函数:
class QuizRepository(var qdao: QuizDao) {
    suspend fun loadQuestions(difficulty: String): List<Quiz> = qdao.loadQuiz(difficulty)
}
  • ViewModel使用viewModelScope在IO线程执行查询:
@HiltViewModel
class GameViewModel @Inject constructor(var quizRepository: QuizRepository) : ViewModel() {
    val quizList = MutableLiveData<List<Quiz>>()

    init {
        loadAllQuestion()
    }

    private fun loadAllQuestion() {
        viewModelScope.launch(Dispatchers.IO) {
            val questions = quizRepository.loadQuestions("Easy")
            withContext(Dispatchers.Main) {
                quizList.value = questions
            }
        }
    }
}

viewModelScope是ViewModel自带的协程作用域,会在ViewModel销毁时自动取消协程,避免内存泄漏。

4. 验证查询条件匹配性

确认预插入记录的difficulty字段值确实为"Easy"(注意大小写,SQLite默认大小写不敏感,但存储值为"easy"等格式时会导致查询为空)。可通过SQLite工具执行SELECT * FROM quiz WHERE difficulty LIKE '%easy%'验证。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 11:05:13