#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).