Hey guys, I have 3 methods inside a `ViewModel` in the image below, calling methods on some reposito...
o
Hey guys, I have 3 methods inside a
ViewModel
in the image below, calling methods on some repository. All methods attempt to do the same thing: Fetch a value from the local DB (a Room DB), suspend the method execution until that value is fetched so the method is guaranteed to return a value. In each method I added a comment that specifies what issue I have with this method. What is the safe and correct way to accomplish what I am trying to do? Slack Conversation
e
launch
is a fire-and-forget construct which exits immediately after you invoke it, so it’s not guaranteed that your
viewModelScope.launch
will run or complete before your function returns in
getCityByID
. What you probably want to do there is turn
getCityByID
into a
suspend fun
and just do something to the effect of:
Copy code
val city = withContext(viewModelScope) {
    locationRepository.getSingleCityFromDatabaseByID(selectedCityID)
}
return city
if you need to run that inside the viewModelScope and not the caller’s scope. If you’d rather run in the caller’s scope you can simply do:
Copy code
return locationRepository.getSingleCityFromDatabaseByID(selectedCityID)
as long as you make it a
suspend fun
. Same concept applies across your other two functions as well.
👍 1
If you’re okay with blocking a thread you can also use
runBlocking(viewModelScope) { …
That way you wouldn’t need to make it a suspend fun
I’d recommend making it a suspend fun though
o
Thanks @Evan R.! your solution is way much cleaner than what I used by far (I used LiveData and observables)
👍 1
e
Yup, coroutines should just look like blocking code 🙂
👍 1
⏸️ 1
o
@Evan R. I can’t call the above code:
Copy code
suspend fun test(selectedCityId: Int, selectedLanguages: List<Int>, selectedExpertiseFieldId: Int){
    val city = withContext(viewModelScope){
        locationRepository.getSingleCityFromDatabaseByID(selectedCityID)
    }
    return city
}
message has been deleted
e
Try
viewModelScope.context
d
how about just using
async
instead of launch:
Copy code
suspend fun getCityById(selectedCityId: Int): City =
    viewModelScope.async {
        locationRepository.getSingleCityFromDatabaseByID(selectedCityID)
    }.await()
👍 1
o
@dfriehs Seems cleaner, but where did I called
launch
? I assume I implicitly did that when calling
withContext
am I correct?
d
You used
launch
in your initial example; I am not exactly sure about implementation details of
withContext
, sadly.
🍻 1
o
Sure thank you @dfriehs