android - Kotlin Flow How to combine two flows and only emit the result when the first flow sends element - TagMerge
3Kotlin Flow How to combine two flows and only emit the result when the first flow sends elementKotlin Flow How to combine two flows and only emit the result when the first flow sends element

Kotlin Flow How to combine two flows and only emit the result when the first flow sends element

Asked 10 months ago
4
3 answers

If flowA doesn't contain repeated elements, or if you're ok to "not trigger" on repeated elements of A, you could achieve what you want with zip and distinctUntilChangedBy like this:

val flowA = flowOf("a", "b", "c")
val flowB = flowOf(1, 2, 3)

val resultFlow = flowA.zip(flowB)
                      .distinctUntilChangedBy { (a, _) -> a }
                      .map { (a, b) -> TODO("combine a and b") }

Another option is making a StateFlow out of B and accessing the latest value when you need it (but it requires a scope to collect B in the state, so it makes this code half hot):

val flowA = flowOf("a", "b", "c")
val flowB = flowOf(1, 2, 3)

val stateB = flowB.stateIn(someScope)
val resultFlow = flowA.map { a -> 
    val b = stateB.value
    TODO("combine a and b")
}

Source: link

0

If flowA doesn't contain repeated elements, or if you're ok to "not trigger" on repeated elements of A, you could achieve what you want with zip and distinctUntilChangedBy like this:
val flowA = flowOf("a", "b", "c")
val flowB = flowOf(1, 2, 3)

val resultFlow = flowA.zip(flowB)
                      .distinctUntilChangedBy { (a, _) -> a }
                      .map { (a, b) -> TODO("combine a and b") }
Another option is making a StateFlow out of B and accessing the latest value when you need it (but it requires a scope to collect B in the state, so it makes this code half hot):
val flowA = flowOf("a", "b", "c")
val flowB = flowOf(1, 2, 3)

val stateB = flowB.stateIn(someScope)
val resultFlow = flowA.map { a -> 
    val b = stateB.value
    TODO("combine a and b")
}

Source: link

0

Let’s take a look at the signature of the combine operator. It’s an extension function on Flow that takes another Flow as an argument to combine with. The second argument is a lambda, which gives you values a: T1 and b: T2 that were emitted recently from both Flows. In the lambda, we can perform the transformations.
Flow<T1>.combine(    flow: Flow<T2>,    transform: suspend (a: T1, b: T2) -> R): Flow<R> (source)
Now, let’s see how it works. Each time an emission from either one of the flows occurs, the combine operator takes the latest emission from two flows and provides the results in the lambda expression as number and letter:
numbersFlow.combine(lettersFlow) { number, letter ->    "$number$letter"}
By using the collect operator, we can get the result as shown. Now let’s see the output.
Output1A2A3A3B3C
Let’s take a look at the signature of the zip operator. This is another extension function on Flow that takes another Flow as an argument. The second argument is a lambda, which gives you values T1 and T2. The critical difference from the combine is that the resulting Flow completes as soon as one of the flows completes and cancel is called on the remaining Flow.
public fun <T1, T2, R> Flow<T1>.zip(    other: Flow<T2>,    transform: suspend (T1, T2) -> R): Flow<R> = zipImpl(        this, other, transform )
Now, let’s see how this works. Each time an emission occurs, from either of the flows, the zip operator waits for emission from the other Flow. When it occurs, zip emits both results as number and letter:
numbersFlow.zip(lettersFlow) { number, letter ->    "$number$letter"}

Source: link

Recent Questions on android

    Programming Languages