0
votes

This question is in regard to the best practices in Android programming using MVVM, LiveData, Room (and hence also RetroFit) and co-routines. One of the best practises states that

Long running executions such as Network - or Database calls should be performed asynchronous from the UI thread.

Current documentation and blogs explain how to do this in detail using co-routines and some examples are demonstrating this nicely, e.g. the Sunflower App.

The part I am missing is when a ViewModel is initialized and it needs to show content from the database/repository/network, how the loading using co-routines is done. In the Sunflower App the repository is returning LiveData, but there is no use of co-routines.

Example:

In PlantDao we see:

@Query("SELECT * FROM plants WHERE id = :plantId")
fun getPlant(plantId: String): LiveData<Plant>

There is no suspend keyword hence, this is not part of a co-routine.

In plantRepository there is:

fun getPlant(plantId: String) = plantDao.getPlant(plantId)

Again no suspend keyword so no co-routine.

In the PlantDetailViewModel the initialization shows us

val plant = plantRepository.getPlant(plantId)

So no scope, Job or any co-routine related stuff.

My questions:

  • Is room performing the DB query asynchronous? And if so, is it using co-routines?
  • Is this a good practice? Because the repo is only returning LiveData and can only be used to return LiveData
  • What are other strategies to do this? Any examples?
  • Would this strategy differ for network requests?
1

1 Answers

3
votes

Is room performing the DB query asynchronous? And if so, is it using co-routines?

It is performing asynchronous and no, it does not use coroutines. LiveData is lifecycle aware, so it's called only when it is observed by a resumed LifecycleOwner, like a Fragment.

Is this a good practice? Because the repo is only returning LiveData and can only be used to return LiveData

Kind of. If you watch https://www.youtube.com/watch?v=zbYYoL7vo9Y and https://www.youtube.com/watch?v=B8ppnjGPAGE, you can see that they're steering away from using LiveData in your repo or datasource and instead use coroutines in those layers. The important thing is to understand which coroutine scope your call belongs to. F.i., should it finish when the user does not see the result?

What are other strategies to do this? Any examples? Would this strategy differ for network requests?

The new hot thing in Android town is to use coroutines in combination with Flow. If you use Retrofit for network calls, this now supports coroutines and as well. A nice code lab to check out is this one: https://codelabs.developers.google.com/codelabs/kotlin-coroutines/#0