MR3YY
MR3YY

Reputation: 694

Flow<List<T>> instead of using Flow<T>?

I've noticed that many people and examples Use Flows as a Wrapper around List<>, For example like this:

@Query("SELECT * from some_model ORDER BY some_field")
fun getData(): Flow<List<some_model>>

As I know the Flow is like kind of "asynchronous sequences", so I really didn't get the meaning of "Flow<List< T >>".

why we can't just use Flow< T > directly which seems intuitive to me, I ask this question because I saw this repeated many times in code snippets and Cannot understand the purpose behind it??

Upvotes: 3

Views: 666

Answers (1)

Nicolas
Nicolas

Reputation: 7111

That's the same question I asked myself when I started using Flow.

You might think that using Flow with Room would fetch the data from the query partially at first, making data available through the flow as it is obtained from the database. That would effectively use something like Flow<T>. However, that's not the idea here, this is more something you would get with Paging.

Instead, when you call getData() you get a Flow<List<T>> that will emit a whole new list every time the result of the query changes, as well as an initial value. SELECT statements always produce lists with Room, never single values. So let's say you collect the flow at one place:

dao.getData().collect { list ->
    Log.d(TAG, list.joinToString())
}

And you change the database afterwards:

dao.insert(...)
dao.insert(...)

There will be 3 log messages written, one for the initial value, and two for the subsequent changes made. This might seem very inefficient at first (which is why I didn't really understand it at first), but in practice the performance impact is negligible on most devices, even with thousand of rows. And it allows for a very clean implementation of lists when combined with ListAdapter and DiffUtil.

I hope that answers your question.

Upvotes: 6

Related Questions