Home > OS >  Should Kotlin Flows be used when passing a single object to ViewModel in Android?
Should Kotlin Flows be used when passing a single object to ViewModel in Android?

Time:01-14

On varius occasions I've seen people use Kotlin Flows when retrieving a list of objects from a local database, but nowhere have I noticed any warning/error about using them when retrieving single objects (as opposed to a list), or even specification that Flows are to be used only on lists

My question is, will using Flows on single objects cause an error/problem? If not does it hinder performance? In case no, why is it generally not used then?


Sample code of what I mean:

  • Single object retrieval with Flows:
@Query("SELECT * FROM objects WHERE id = :id")
fun getObjectById(id: Int): Flow<Object>
  • Retrieving function in ViewModel:
fun objectRetrieval(id: Int) {

    // ... More code

    getObjectById(id)
        .onEach { object: Object ->
            // Operations
        }
        .launchIn(viewModelScope)
}

Thank you for your time!

CodePudding user response:

Yes you should flow single objects Singe Source of Truth Architecture

val numLightsObserver: Observer<Int> = Observer { i: Int ->
        i.let { jx.setTitle(i.toString()) }
    }
    wordViewModel.numLights.observe(this, numLightsObserver)

Now I have a fully automated object for my UI what will I do with the number of lights. Above I convert it to a string for this demo commit.

here's a link to commit diff I had to modify 4 files to make it work diff on github where I try it flow a single object

CodePudding user response:

I think there are multiple misconceptions here, both in the question and in comments/answer.

Flows are indeed related to sequences of values processed asynchronously. In simple words that means: if in the future we plan to receive some data multiple times, flows are just for this purpose. Examples are: user events, incoming messages in an instant messaging application, etc.

If we plan to receive the data only once, we can still use flow, but this is an overkill and it adds unnecessary complication. In these cases it is better to use a suspend function as it is easier to use and it is very clear about the fact the data is received only once.

However, it doesn't really matter, if the data we receive is a single object or a list of objects. As a matter of fact, list is an object as well:

  • suspend fun foo(): String - receive a single object once.
  • suspend fun foo(): List<String> - receive a list of objects, all at once.
  • fun foo(): Flow<String> - receive a single object multiple times.
  • fun foo(): Flow<List<String>> - receive a list of objects multiple times.

All of above cases make sense and can be used in different scenarios.

Now, going to your specific example, there is another misconception there. Your getObjectById() doesn't receive only a single value, but a sequence of values. By using Flow we say to Room that we want to observe the data for changes. First, it sends you the current data for the object, but if the object ever changes, you receive updated data again.

If you want to only get the current data and do not observe for changes, use a suspend function instead.

  • Related