Home > Software design >  How to trigger Kotlin Flow sequentially and combine the result together?
How to trigger Kotlin Flow sequentially and combine the result together?

Time:05-20

As title, I got two flows and need to trigger them sequentially first then combine the result.

data class User(
    val name: String, 
    val age: Int,
)

data class UserStatus(
    val status: String, 
)

val flow1 = flow {
    delay(300L)
    emit(User("Tony Stuck", 50))
}

val flow2(age: Int) = flow {
    val result = when {
        age > 60 -> "Over 60"
        age < 60 -> "Under 60"
        else -> "Equal 60"
    }
    delay(500L)
    emit(UserStatus(result))
}

// The code below isn't what I expected
flow1.flatMapMerge {
        flow2(it.age)
    }
    .collect {
        // here I get **UserStatus**, but I want Pair(User, UserStatus)
    }

I'v tried using flatMapMerge, but it will map to flow2 finally, what I expect to get is Pair(User, UserStatus), is there any better way to deliver this ?

CodePudding user response:

You can try the following:

flow1.flatMapMerge { user ->
    flow2(user.age).map { userStatus ->
        user to userStatus
    }
}.collect { pair ->
    // pair is of type Pair<User, UserStatus>
}

CodePudding user response:

Assuming flow2 is a function and not a variable since it looks like you are passing a parameter, why is flow2 a Flow at all? It only returns one thing. That's better suited for a suspend function or a function that returns a Deferred.

suspend fun getStatus(age: Int): UserStatus {
    val result = when {
        age > 60 -> "Over 60"
        age < 60 -> "Under 60"
        else -> "Equal 60"
    }
    return UserStatus(result)
}


flow1.map {
    it to getStatus(it)
}
.collect {
    // this is Pair(User, UserStatus)
}

If you really need flow2 to be a Flow and its first result is the value you need, then:

flow1.map {
    it to flow2(it).first()
}
.collect {
    // this is Pair(User, UserStatus)
}
  • Related