在 Kotlin 流程中取消后发出
Emit after cancellation in Kotlin flow
我有以下代码的更复杂版本:
val testFlow = flow {
try {
// Continually emit some values
} catch (e: CancellationException) {
// Wrap up and emit finished state value
}
}
当我收集这个 testFlow 时,我从未收到完成状态值。 documented 流生成器在发出值之前执行 ensureActive 检查。在此 link 中也是一个使用 IntRange.asFlow
的示例,它在发出值之前不检查取消并显示继续收集这些值。
有没有办法让自定义 kotlin 流在取消协程后发出要收集的最后一个值?
这里有一个 Kotlin Playground example(感谢 @Tenfour04)显示取消后发出的不同行为,具体取决于流程的构建方式。我只是不知道如何获得不是由 IntRange.asFlow
.
构造的取消后能够发出的流
IntRange.asFlow
在内部使用 unsafeFlow 定义为:
inline fun <T> unsafeFlow(crossinline block: suspend FlowCollector<T>.() -> Unit): Flow<T> {
return object : Flow<T> {
override suspend fun collect(collector: FlowCollector<T>) {
collector.block()
}
}
}
使用 unsafeFlow 甚至可以在已取消的协程中发出信号,尽管这个解决方案是一个 hack,我想用一个不需要访问内部 Kotlin Coroutine API 的更官方支持的版本来替换它。
注意:取消后发射仅在使用
时有效
try {
...
} catch (e: CancellationException) {
...
}
并且不使用 unsafeFlow.catch {}
。
我有以下代码的更复杂版本:
val testFlow = flow {
try {
// Continually emit some values
} catch (e: CancellationException) {
// Wrap up and emit finished state value
}
}
当我收集这个 testFlow 时,我从未收到完成状态值。 documented 流生成器在发出值之前执行 ensureActive 检查。在此 link 中也是一个使用 IntRange.asFlow
的示例,它在发出值之前不检查取消并显示继续收集这些值。
有没有办法让自定义 kotlin 流在取消协程后发出要收集的最后一个值?
这里有一个 Kotlin Playground example(感谢 @Tenfour04)显示取消后发出的不同行为,具体取决于流程的构建方式。我只是不知道如何获得不是由 IntRange.asFlow
.
IntRange.asFlow
在内部使用 unsafeFlow 定义为:
inline fun <T> unsafeFlow(crossinline block: suspend FlowCollector<T>.() -> Unit): Flow<T> {
return object : Flow<T> {
override suspend fun collect(collector: FlowCollector<T>) {
collector.block()
}
}
}
使用 unsafeFlow 甚至可以在已取消的协程中发出信号,尽管这个解决方案是一个 hack,我想用一个不需要访问内部 Kotlin Coroutine API 的更官方支持的版本来替换它。
注意:取消后发射仅在使用
时有效try {
...
} catch (e: CancellationException) {
...
}
并且不使用 unsafeFlow.catch {}
。