DDukesterman
DDukesterman

Reputation: 1399

Combining two StateFlows into one stream

I am currently trying to combine two streams and use that result to display into a Compose view in Android. I currently initialize it like this:

private var flowA: MutableStateFlow<String?> = MutableStateFlow(null)
private var flowB: MutableStateFlow<String?> = MutableStateFlow(null)

var combinedFlows: Flow<Pair<String?, String?>> =
    flowA.combine(flowB) {a, b ->
        Pair(a, b)
    }

Emit like so:

// Some logic to create string
flowA.emit("New String") 

// More logic to create another string
flowB.emit("Another New String")

In the compose view I am collecting like this:

var pairStrings = viewModel.pairStrings.collectAsState()

The combined stream is never emiting any data when I emit from flowA and flowB. Is there something I am missing here?

--Edit--

This is in the view model:

val pairStrings: StateFlow<Pair<String?, String?>> = combinedFlows
    .stateIn(
        scope = viewModelScope,
        initialValue = Pair(null,null),
        started = SharingStarted.Eagerly,
    )

Upvotes: 1

Views: 2905

Answers (1)

nglauber
nglauber

Reputation: 23894

You didn't provide much information, but you need to run/subscribe to the combined flow. I think you need to do the following:

val combinedFlows = flowA.combine(flowB) { a, b ->
    a to b // will emit a Pair with the latest value of flowA and flowB
}.shareIn(viewModelScope, SharingStarted.WhileSubscribed())

The shareIn operator runs the upstream flow in a separate coroutine. Doing this, you'll be able to consume the flow. You need to pass a CoroutineScope, assuming you're doing this call in a ViewModel (which should be the best place), you can use the viewModelScope. You also need to pass the SharingState which will determine the strategy that controls when sharing is started and stopped. In this case, I'm using WhileSubscribed which immediately stops the flow when the last subscriber disappears.

Upvotes: 1

Related Questions