Skip to content

Flattening Flow: FlatMapConcat or FlattenConcat

Devrath edited this page Jan 23, 2024 · 4 revisions

When to use flattenConcat

When there is a flow of flows and we want the value from the inner flow, We can use the flattenConcat operator

What is FlatMapConcat

Also the flatMapConcat is a combination of map + flattenConcat

Thread on which it is used

Observe it uses a same co-routine to run synchronously one after another

Without flattening

Output

kotlinx.coroutines.flow.SafeFlow@2836a3c
kotlinx.coroutines.flow.SafeFlow@2bab3c5
kotlinx.coroutines.flow.SafeFlow@ba2c11a
kotlinx.coroutines.flow.SafeFlow@f3e544b
kotlinx.coroutines.flow.SafeFlow@83aee28

Code

class FlattenFlowsDemoVm @Inject constructor(
    @ApplicationContext private val context: Context,
) : ViewModel() {

    private val rootScope = CoroutineScope(context = Dispatchers.IO)

    /**
     * Flow of integers
     */
    fun generateIntegers() = flow {
        repeat(100){
            delay(1000)
            emit(it)
        }
    }


    /**
     * Generate a flow of strings
     */
    fun generateFlowOfStrings(value : Int) = flow {
        val content = "Current string no -->$value"
        println("<Emitted> -->$value")
        emit(content)
    }


    fun flatMapConcatDemo() = rootScope.launch(CoroutineName("FlatMapConcatDemo")){

       val result : Flow<Flow<String>> = generateIntegers()
           .take(5)
           .map {
               generateFlowOfStrings(it)
           }

        result.collect{
            println(it)
        }
    }
    
}

With flattening

Output

<Emitted> -->0
Current string no -->0 at the threadDefaultDispatcher-worker-1
<Emitted> -->1
Current string no -->1 at the threadDefaultDispatcher-worker-1
<Emitted> -->2
Current string no -->2 at the threadDefaultDispatcher-worker-1
<Emitted> -->3
Current string no -->3 at the threadDefaultDispatcher-worker-1
<Emitted> -->4
Current string no -->4 at the threadDefaultDispatcher-worker-1

Code

class FlattenFlowsDemoVm @Inject constructor(
    @ApplicationContext private val context: Context,
) : ViewModel() {

    private val rootScope = CoroutineScope(context = Dispatchers.IO)

    /**
     * Flow of integers
     */
    fun generateIntegers() = flow {
        repeat(100){
            delay(1000)
            emit(it)
        }
    }


    /**
     * Generate a flow of strings
     */
    fun generateFlowOfStrings(value : Int) = flow {
        val content = "Current string no -->$value at the thread${Thread.currentThread().name}"
        println("<Emitted> -->$value")
        emit(content)
    }


    fun flatMapConcat() = rootScope.launch(CoroutineName("FlatMapConcatDemo")){

       // Way-1
       /* val result : Flow<Flow<String>> = generateIntegers()
           .take(5)
           .map {
               generateFlowOfStrings(it)
           }

        result.flattenConcat().collect{
            println(it)
        }*/


        //Way-2
        generateIntegers()
            .take(5)
            .flatMapConcat {
                generateFlowOfStrings(it)
            }.collect{
                println(it)
            }

    }

}
Clone this wiki locally