irobotxx
irobotxx

Reputation: 6063

Combine multiple Flow<List<T>> to a Single Flow<Map<String, List<T>>>

I am trying to convert multiple Flow results from different @Query on Room database to a Flow of Map of those result List. Something like this:

 fun getA(): Flow<List<T>> // query 1

 fun getB(): Flow<List<T>>// query 2

I tried doing something like this:

fun getMappedList(): Flow<Map<String, List<T>>> {

    val mapList = mutableMapOf<String, List<T>>()
    
    return flow {
        getA().map{
          mapList["A"] = it
       }
        getB().map{
          mapList["B"] = it
        }

         emit(mapList)
      }
    
    }

But clearly that seems not to be working. Any ideas how i can achieve this. Many thanks in advance

Upvotes: 2

Views: 3718

Answers (1)

Mark
Mark

Reputation: 9929

I haven't really used the Flow api much, but something like this should work :

fun getMappedList(): Flow<Map<String, List<Int>>> 
        = getA().combine(getB()) { a, b  ->  mapOf(Pair("A", a), Pair("B", b))  }

Or depending on your usecase you might want to use the zip operator, to emit as unique "pairs" :

fun getMappedList(): Flow<Map<String, List<Int>>> 
        = getA().zip(getB()) { a, b  ->  mapOf(Pair("A", a), Pair("B", b))  }

Tested using :

fun getA(): Flow<List<Int>> = flow { emit(listOf(1)) }

fun getB(): Flow<List<Int>> = flow { emit(listOf(2)); emit(listOf(3)) }

fun getCombine(): Flow<Map<String, List<Int>>> 
           = getA().combine(getB()) { a, b  ->  mapOf(Pair("A", a), Pair("B", b))  }

fun getZip(): Flow<Map<String, List<Int>>> 
           = getA().zip(getB()) { a, b  ->  mapOf(Pair("A", a), Pair("B", b))  }

output in the collector for combine (combines latest values from either flow) :

{A=[1], B=[2]}

{A=[1], B=[3]}

output in the collector for zip (zip pairs of emissions from each flow) :

{A=[1], B=[2]}

Update

Having used the api a bit more you can use combine which can take n number of Flow<T> :

val flowA =  flow<Int> { emit(1) }
val flowB =  flow<Int> { emit(2) }
val flowC =  flow<Int> { emit(3) }
    
combine(flowA, flowB, flowC, ::Triple)

Upvotes: 4

Related Questions