我需要在.combineLatest()
ReceiveChannel
扩展功能
suspend fun <A, B, R> ReceiveChannel<A>.combineLatest(
otherSource: ReceiveChannel<B>,
context: CoroutineContext = Unconfined,
combineFunction: suspend (A, B) -> R
): ReceiveChannel<R> = produce(context) {
// ?
}
我希望它能像RxJava&#39; s combineLatest()
一样发挥作用。
我该怎么做?
编辑:到目前为止,我有这个,但它不起作用。sourceB.consumeEach{ }
块永远不会被删除。
suspend fun <A, B, R> ReceiveChannel<A>.combineLatest(
otherSource: ReceiveChannel<B>,
context: CoroutineContext = Unconfined,
combineFunction: suspend (A, B) -> R
): ReceiveChannel<R> = produce(context) {
val sourceA: ReceiveChannel<A> = this@combineLatest
val sourceB: ReceiveChannel<B> = otherSource
var latestA: A? = null
var latestB: B? = null
sourceA.consumeEach { a ->
latestA = a
if (latestA != null && latestB != null) {
send(combineFunction(latestA!!, latestB!!))
}
}
sourceB.consumeEach { b ->
latestB = b
if (latestA != null && latestB != null) {
send(combineFunction(latestA!!, latestB!!))
}
}
}
我还想确保当此函数返回的ReceiveChannel<R>
关闭(取消订阅)时,我想确保父通道正确关闭。
答案 0 :(得分:0)
这就是诀窍!我仍然感到困惑,为什么我可以将一个.consumeEach{ }
嵌套在另一个.consumeEach { }
中 - 这似乎不直观。
suspend fun <A, B, R> ReceiveChannel<A>.combineLatest(
otherSource: ReceiveChannel<B>,
context: CoroutineContext = Unconfined,
combineFunction: suspend (A, B) -> R
): ReceiveChannel<R> = produce(context) {
val sourceA: ReceiveChannel<A> = this@combineLatest
val sourceB: ReceiveChannel<B> = otherSource
val latestA = AtomicReference<A>()
val latestB = AtomicReference<B>()
var aInitialized = false
var bInitialized = false
sourceA.consumeEach { a ->
latestA.set(a)
aInitialized = true
if (aInitialized && bInitialized) {
send(combineFunction(latestA.get(), latestB.get()))
}
launch(coroutineContext) {
sourceB.consumeEach { b ->
latestB.set(b)
bInitialized = true
if (aInitialized && bInitialized) {
send(combineFunction(latestA.get(), latestB.get()))
}
}
}
}
}
答案 1 :(得分:0)
我知道这是一个老问题,但这是一个建议:
我建议使用.zip()
而不是嵌套.consumeEach
。查看文档here。
可能的解决方案sourceA.zip(sourceB).consumeEach{}
会生成类型为Pair的项目。