If I've a flow, but I don't collect it (I only cal...
# coroutines
a
If I've a flow, but I don't collect it (I only call it) - will it execute? For example, consider I've a coroutine that retrieves a set of documents from the database. If I call this coroutine (that returns a flow) as
val myCall = coroutineReturningFlowCall()
but I don't
collect
it, will the call to the database be made? Or only when I collect will the execution of the code be done?
r
that entirely depends on what that function does. If it's a typical flow{} builder, then it's a cold flow and as such that code will be executed only upon collection. If it's a mutable shared flow and you just eagerly emit something onto it when you call this function, then it's a hot flow.
thank you color 1
☝️ 1
z
This is a pretty common gotcha when writing flows.
Copy code
fun createFlow(): Flow<Foo> {
  val results = db.query()
  return flow {
    emitAll(results)
  }
}
Vs
Copy code
fun createFlow(): Flow<Foo> {
  return flow {
    val results = db.query()
    emitAll(results) 
  }
}
👍 2
s
One common way to avoid making this mistake ^^ is to never make a function which returns a flow a
suspend
function. If it's not suspending itself, and your .query() function is supsend itself you wouldn't even be able to write this in the first place, and boom, you caught this problem immediately. Just gotta remember not to just auto-accept the IDE suggestion to make the function suspending 😅
5
☝🏻 1
☝️ 1
g
It really should be a warning on the level of ide But a custom lint rule is also nice for this
One more good rule, is to avoid write functions which return flow if semantically it can be replaced by suspend function (like in example above), so keep business logic as suspend function, and use an extension to convert suspend function to flow if necessary for specific case, like db::query.asFlow()
1