https://kotlinlang.org logo
Title
d

Dennis Schröder

10/01/2019, 9:52 PM
I recently read something that I interpreted as being bad.
suspend fun someFunctionCreatesAFlow(context: Dispatchers.Default): Flow<String> = withContext(context) {
 flow {
    emit(somethingAsAString)
   } 
}
I guess it is because Flows kinda manage their own context with
flow::flowOn()
. Can anybody confirm this?
So I guess this is the right way ... ?
suspend fun someFunctionCreatesAFlow(context: Dispatchers.Default): Flow<String> = coroutineScope {
 flow {
    emit(somethingAsAString)
   } .flowOn(context)
}
d

Dominaezzz

10/01/2019, 9:59 PM
suspend fun someFunctionCreatesAFlow(context: Dispatchers.Default): Flow<String> = flow {
    emit(somethingAsAString)
   } .flowOn(context)
d

Dennis Schröder

10/01/2019, 9:59 PM
Ohh well yeah but in my actual use case `somethingAsAString`is of type
suspend CoroutineScope.() -> String
. Therefore I need a scope
o

octylFractal

10/01/2019, 9:59 PM
it's not bad necessarily, but iirc
flow
isn't a suspend function itself, only terminal operations, so it doesn't pass any of the context to the flow. technically that function doesn't need to be suspend at all
d

Dennis Schröder

10/01/2019, 9:59 PM
But I forget to mention sorry
o

octylFractal

10/01/2019, 10:00 PM
if you need a scope, create it inside
flow { }
e.g.
flow {
  coroutineScope {
     ...
  }
}
👍🏼 1
l

louiscad

10/01/2019, 11:08 PM
Don't make is suspending, just use
flowOn
.
1
s

streetsofboston

10/01/2019, 11:40 PM
What Louis said. The creation of a Flow has/needs no context/scope. The collector of the Flow, however does need one, and that will be the same scope that is used when your Flow's emitter (that suspend-lambda) is called.
p

Pablichjenkov

10/02/2019, 9:00 PM
If I call
Flow.collect()
from a scope that has a Dispatcher.UI type. Will the flow chain process in this UI scope by default? Am I forced to use
flowOn(IOContext)
to make it execute off the UI thread?
s

streetsofboston

10/02/2019, 9:04 PM
@Pablichjenkov That is not necessary a problem. As long as you don’t have blocking code in your Flow, you should be all set. If you have suspending code inside your Flow, that is not a problem either, since suspending won’t block the UI thread
p

Pablichjenkov

10/02/2019, 9:08 PM
Well by flow chain process I mean flows that have suspending functions inside and either IO or heavy computation blocks. Where these suspending blocks will be executed if not passed any Dispatcher explicitly, Dispatcher.Default?
l

louiscad

10/02/2019, 9:16 PM
All the info about that is already in kotlinx.coroutines docs. You can verify what you see in the docs, that should help you understand what to expect.
o

octylFractal

10/02/2019, 9:18 PM
flows run on the same dispatcher as whatever calls the terminal operations, unless you use
flowOn
, then everything setup before that call runs in the context passed there (calls after
flowOn
still use the same dispatcher as the terminal op caller)
p

Pablichjenkov

10/02/2019, 9:37 PM
@octylFractal I read what you just said, however, my concern was about the following: You have 2 types of code in a flow, lets say.
// case 1
flow {

    suspendingBlockingFunc()

}
//and case 2
flow {

    nonSuspendingBlockingFunc() // Blocks either by IO or heavy CPU

}
If not using
flowOn
operator and calling
collect()
from Dispatcher.UI. Case 1 flow will execute on UI killing it Case 2 flow will execute on where? -> Default?
o

octylFractal

10/02/2019, 9:38 PM
exactly what I said, the same dispatcher as
collect()
that is, case 1 & 2 are the same, there is no difference in how they are executed besides what the function they call does
p

Pablichjenkov

10/02/2019, 9:39 PM
I see it now. There is no magic behind it.
thnks