I have a `Flow<List<Foo>>`, then I need to subscri...
# coroutines
u
I have a
Flow<List<Foo>>
, then I need to subscribe
FooDetails
where such flow is accessed by
foo.id
Copy code
allFoos
  .flatMapLatest { foos -> ..fooDetailsProvider.fooDetails(each foos.id) ???
basically I need the flatMap lambda to return a
List<Flow<FooDetails>>
, i.e. for each of
foos
I need to subscribe a
fooDetailsProvider.fooDetails(it.id)
Any idea as how to do this?
d
There might be a flowOf() method?
u
not sure what you mean
d
Actually, it doesn't really make sense to go from a "flow of lists" to a "list of flows".
For one thing, if the list size changes, the there is no way the "list of flows" would be valid after that.
What are you actually trying to do?
u
I have a flow of Foos and then a function that returns flow of foo details, but it takes a fooId
what im trying to do is get foo detaiks for all foos
d
So maybe you want
allFoos.map { list -> list.map { fooDetailsProvider.fooDetails(it.id) } }
u
well that will return list of flows, but I need to collect them
d
Oh, does fooDetailsProvider return a flow?
u
yes
d
Ah.
u
so a flatMap of sorts but I need to somehow subscribe all of the mapped flows, idk how
d
So the setup is soemthing like this:
Copy code
data class Foo(val id: String)
class FooDetails

interface FooDetailProvider {
    fun getDetails(id: String): Flow<FooDetails>
}
u
yes
d
Copy code
fun Flow<List<Foo>>.details(provider: FooDetailProvider): Flow<List<FooDetails>> =
    map { foos ->
        foos.map { foo ->
            provider.getDetails(foo.id).single()
        }
    }
u
I'm hacking around with
flow { .. }
but what it ended up being is not what I want, it emitted each detail right away
d
Unless the details change over time though, the provider should probably return a
Deferred<FooDetails>
instead though.
u
why, normal Flows are fine, usual reactive stuff
at the end what I want is
List<FooAndFooDetails>
d
Copy code
data class Foo(val id: String)
class FooDetails

interface FooDetailProvider {
    fun getDetails(id: String): Deferred<FooDetails>
}

fun Flow<List<Foo>>.details(provider: FooDetailProvider): Flow<List<Pair<Foo, FooDetails>>> =
    map { foos -> foos.map { foo -> foo to provider.getDetails(foo.id).await() } }
u
that only pulls the details at the time of mapping, I need the whole thing to be reactive, both Foo and FooDetails might change in time, jndependently
d
So when I asked what you're actually trying to do... That was what I was getting at.
So, maybe what you want is a
Flow<List<Pair<Foo, Flow<FooDetails>>>>
Or lets put it another way, what is the consumer going to do with this data?
u
I need this
oneFoo.flatMapLatest { provider.details(it.id }
but over all foos, i.e a
Flow<List<Foo>>
I don't have a
Provider.allDetails(ids)
but unfortunatelly just a
Provider.details(id)
So I need to subscribe that function n-times and then somehow combine all the emits for each of the subscriptions
d
Copy code
fun Flow<List<Foo>>.details(provider: FooDetailProvider): Flow<List<Pair<Foo, FooDetails>>> =
    flatMapLatest { foos ->
        val list = foos.map { foo ->
            provider.getDetails(foo.id).map { foo to it }
        }
        combine(list) { it.toList() }
    }
I think this will do what you want.
u
omg theres a combine that takes a list, ofc
amazing thank you
d
Copilot answered this one, so I can't take full credit.
u
which one 😀
d
GitHub Copilot was what suggested
combine(list)
code for me, once I set the rest of the context.
u
works, thanks!
d
kodee happy