Запрос комнаты Android возвращает значение null

#android #sql #kotlin #android-room #dao

Вопрос:

Я пытаюсь получить значения из базы данных через комнату, но она всегда возвращает значение null. Он должен извлекать данные из базы данных BalancesCat. Какая-нибудь помощь? Спасибо!

Это и есть ДАО

 @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
    }
 

Модель представления

 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)
   }
}
 

Ответ №1:

Это не ваша проблема, но я должен упомянуть, getAllBalancesCat() что функция вашего репозитория излишне сложна и ей не нужно возвращать значение null. Поскольку balancesCatDao.getAllBalances() это suspend функция, ее бессмысленно оборачивать withContext() . Вам никогда не нужно указывать контекст для вызова функции приостановки (если только функция приостановки не была разработана неправильно и в ней не содержится код блокировки). Это можно упростить до:

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

Ваша функция ViewModel неверна и гарантированно всегда возвращает значение null. Он создает переменную balancesCat с начальным значением null, запускает сопрограмму, а затем возвращает значение null balancesCat еще до ее запуска. Сопрограммы в области ViewModel добавляются в очередь петлителя основного потока, но это помещает их после кода, который в данный момент выполняется в основном потоке, как и остальная часть этой функции.

Правильный способ работы этой функции ViewModel-также быть функцией приостановки, которая возвращает список, не допускающий обнуления:

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

И в своем фрагменте запустите сопрограмму из lifecycleScope , чтобы выполнить всю эту работу, которая частично включает вызов функции(функций) приостановки.

Я не могу много комментировать фрагмент кода, потому что он не показан в контексте, но я вижу некоторые возможные запахи кода. Свойства, которые, вероятно, должны быть просто локальными val в функции. Фрагменту не нужно получать значения из ViewModel, а затем сохранять их в свойствах, и если это так, то код Фрагмента усложняется, потому что он должен проверять, содержит ли локальное свойство актуальное значение или нет, вместо того, чтобы просто получать его из источника (ViewModel).