I'm wrapping my head around Kotlin coroutines and LiveData. I want to do really basic use case where ViewModel returns LiveData taken from Repository suspended function, which returns LiveData as well.
Repository function signature:
suspend fun getAll() : LiveData<List<Mountain>>
It can't simply do that:
fun getMountains() : LiveData<List<Mountain>> {
return mountainsRepository.getAll()
}
because the compiler states that suspend function should be called from coroutine or another suspend function. I came up with 2 ugly solutions, but I know they aren't elegant:
1 Solution with runBlocking
fun getMountains() : LiveData<List<Mountain>> = runBlocking { mountainsRepository.getAll() }
2 Solution with nullable LiveData
fun getMountains() : LiveData<List<Mountain>>?{
var mountains : LiveData<List<Mountain>>? = null
viewModelScope.launch{
mountains = mountainsRepository.getAll()
}
return mountains
}
How can I do this properly?
There is a liveData builder that can call suspend functions in its body. So your view model function can look like
fun getMountains() = liveData {
emit(mountainsRepository.getAll())
}
make sure you are using at least
implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.2.0"
And as Lena mentioned - removing suspend
from your repository getAll()
function do not make it blocking.
Having
fun getAll() : LiveData<List<Mountain>>
in your repo, and
fun getMountains() = mountainsRepository.getAll()
in your view model, could be a better way to achieve the same goal