Android 房间查询返回空值

Android Room Query returning null

我试图通过 Room 从数据库中获取值,但它始终 returns 为空。 它应该从 DB BalancesCat 中检索数据。 有什么帮助吗?谢谢!

这是 DAO

@Query("SELECT * FROM BalancesCat")
suspend fun getAllBalances(): List<BalancesCat>

存储库

suspend fun getAllBalancesCat(): List<BalancesCat>? {
        var balancesCat: List<BalancesCat>? = null
        withContext(Dispatchers.IO){
            balancesCat = balancesCatDao.getAllBalances()
        }
        return balancesCat
    }

ViewModel

fun getAllBalancesCat(): List<BalancesCat>? {
        var balancesCat: List<BalancesCat>? = null
        viewModelScope.launch {
            balancesCat = repository.getAllBalancesCat()
        }
        return balancesCat
    }

以及我要检索数据的片段

balancesCatViewModel = ViewModelProvider(requireActivity(),
   BalancesCatViewModelFactory(requireActivity().application)).
   get(BalancesCatViewModel::class.java)

allBalancesCat = balancesCatViewModel.getAllBalancesCat()

var allBalancesCatNew: BalancesCat

val currentDate1 = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd"))
val dateCurrent1 = Date.valueOf(currentDate1)

allBalancesCat?.forEach {
   if(it.date != dateCurrent1){
      it.date = dateCurrent1
      allBalancesCatNew = it
      balancesCatViewModel.update(allBalancesCatNew)
   }
}

这不是你的问题,但我不得不提一下,你的存储库的 getAllBalancesCat() 函数不必要地复杂并且不需要 return 可为空。由于 balancesCatDao.getAllBalances() 是一个 suspend 函数,因此将其包装在 withContext() 中毫无意义。您永远不需要指定上下文来调用挂起函数(除非挂起函数设计不正确并且其中包含阻塞代码)。可以简化为:

suspend fun getAllBalancesCat(): List<BalancesCat> = balancesCatDao.getAllBalances()

您的 ViewModel 函数不正确,并且保证始终 return 为空。它创建初始值为 null 的变量 balancesCat,启动协程,然后在协程启动之前 return 设置空值 balancesCat。 ViewModel 作用域上的协程被添加到主线程循环程序的队列中,但是将它们放在主线程中当前 运行 的代码之后,就像此函数的其余部分一样。

此 ViewModel 函数的正确工作方式也是一个挂起函数,return是一个不可为 null 的列表:

suspend fun getAllBalancesCat(): List<BalancesCat> = repository.getAllBalances()

然后在您的 Fragment 中,从 lifecycleScope 启动协程来完成所有这些部分涉及调用挂起函数的工作。

我不能对片段代码做太多评论,因为它没有在上下文中显示,但我看到了一些可能的代码味道。函数中可能只是局部 vals 的属性。 Fragment 不需要从 ViewModel 获取值,然后将它们存储在属性中,如果需要,那么 Fragment 的代码会变得更加复杂,因为它必须检查本地 属性 是否持有最新的 -日期值与否,而不是仅仅从源(ViewModel)获取它。