Kotlin 组合两个相互依赖的流程

Ale*_*sso 3 kotlin kotlin-coroutines

我有一个数据类,MyThing1其中有一个 ID。数据类 MyThing1(val id: String)\n我有另一个数据类,我们不关心它的内容,但让 \xe2\x80\x99s 调用它MyThing2\n我有一个返回列表的函数MyThing1

\n
fun myEmitter1(): Flow<List<MyThing1>>\n
Run Code Online (Sandbox Code Playgroud)\n

我有另一个 Flow,它接受输入 ID 并返回对象流,所以

\n
fun myEmitter2(id: String): Flow<MyThing2>\n
Run Code Online (Sandbox Code Playgroud)\n

MyThing1对于从流中收到的每个消息,我想将其与MyThing2发出的最新消息结合起来myEmitter2,并返回Flow<List<CombinedThing>>给定的CombinedThingis

\n
data class CombinedThing(val myThing1: MyThing1, val myThing2: MyThing2) .\n
Run Code Online (Sandbox Code Playgroud)\n

每次 myThing1 发生变化时,它都会观察myEmitter2(id)并每次myThing2发出时,都会发出CombinedThing.

\n

在图表中,我想要这样的东西:

\n
[mt11,mt12]--------------------------------------------------------------------------\nobserve for id 1 ----mt211-----------------------------------------------------------\n--[observe for id 2]------------------------mt212-------------------------------------\n\n---------------------[CT(mt11,mt211(1))]----[CT(mt11,mt211(1)),CT(mt2,mt212)]---------\n
Run Code Online (Sandbox Code Playgroud)\n

Sam*_*Sam 6

因此, 的输入应该是来自?myEmitter2的值的 ID。myEmitter1

flatMapLatest我们可以使用和运算符来实现combine

myEmitter1().flatMapLatest { myThing1s: List<MyThing1> ->
    val myThing2s: List<Flow<Pair<MyThing1 to MyThing2>> = myThing1s.map { t1 ->
        myEmitter2(t1.id).map { t2 -> t1 to t2 }
    }
    combine(myThing2s) { combined: Array<Pair<MyThing1, MyThing2>> ->
        combined.map { (t1, t2) -> CombinedThing(t1, t2) }
    }
}
Run Code Online (Sandbox Code Playgroud)

文档中,flatMapLatest创建“一个流,每当原始流发出一个值时,该流就会切换到由转换函数生成的新流”。这符合您“每次myThing1变化,它都会观察myEmitter2(id)”的要求。

flatMapLatest在的转换函数中,我们看到 发出的每个列表myEmitter1。我们用来map将 转换List<MyThing1>为流列表。每个流都会从中获取值myEmitter2并使用map(再次)将它们与原始值配对myThing1。这给了我们一个List<Flow<Pair<MyThing1 to MyThing2>>.

最后,我们使用combine将流列表转换为Flow<List<CombinedThing>>. 该combine运算符获取流列表并发出通过组合每个流中最近发出的值来计算的值。我们得到一个数组(我称之为combined),其中包含每个流的最新值。使用map,我们可以将该数组转换为 aList并将我们的对转换为一个CombinedThing对象。