我有一个流发出多个字符串:
int smallest_element = *min_element(vec.begin(),vec.end());
一段时间后,我想退订该流。目前,我正在执行以下操作:
@FlowPreview
suspend fun streamTest(): Flow<String> = flowViaChannel { channel ->
listener.onSomeResult { result ->
if (!channel.isClosedForSend) {
channel.sendBlocking(result)
}
}
}
如果协程被取消,该流仍将执行。没有订阅者在听新值。如何退订并停止viewModelScope.launch {
beaconService.streamTest().collect {
Timber.i("stream value $it")
if(it == "someString")
// Here the coroutine gets canceled, but streamTest is still executed
this.cancel()
}
}
功能?
答案 0 :(得分:2)
解决方案不是取消流程,而是取消其启动范围。
val job = scope.launch { flow.collect { } }
job.cancel()
答案 1 :(得分:2)
您可以在 Flow 上使用 takeWhile
运算符。
flow.takeWhile { it != "someString" }.collect { emittedValue ->
//Do stuff until predicate is false
}
答案 2 :(得分:1)
当流在 courtin 范围内运行时,您可以从中获取作业以控制停止订阅。
// Make member variable if you want.
var jobForCancel : Job? = null
// Begin collecting
jobForCancel = viewModelScope.launch {
beaconService.streamTest().collect {
Timber.i("stream value $it")
if(it == "someString")
// Here the coroutine gets canceled, but streamTest is still executed
// this.cancel() // Don't
}
}
// Call whenever to canceled
jobForCancel?.cancel()
答案 3 :(得分:0)
使用协程的当前版本/ Flows
(1.2.x),我现在不是一个好的解决方案。借助onCompletion
,您将在流程停止时得到通知,但随后您将无法使用streamTest
函数,因此很难停止监听新事件。
beaconService.streamTest().onCompletion {
}.collect {
...
}
有了协程的下一个版本(1.3.x),这将非常容易。不推荐使用功能flowViaChannel
,而推荐使用channelFlow
。此功能使您可以等待流关闭并在此时进行一些操作,例如。删除监听器:
channelFlow<String> {
println("Subscribe to listener")
awaitClose {
println("Unsubscribe from listener")
}
}