【问题标题】:How to make kotlin flow wait till end before Terminal operator is executed如何在执行终端操作员之前让 kotlin 流程等到结束
【发布时间】:2020-05-27 11:10:04
【问题描述】:
/**
* Does some work and return true to denote success
* false to denote failure
*/
suspend fun doWork(): Boolean {

    val processStatus = processWork()

    return processStatus.filter { status ->
                status == ProcessStatus.SUCCESS 
                || status == ProcessStatus.FAILURE
            }.map { filteredStatus ->
                filteredStatus == ProcessStatus.SUCCESS
            }.single()
}


/**
* Cretaes a channel in which different status will be offered
*/
suspend fun processWork(): Flow<ProcessStatus> {

    val channel = BroadcastChannel(Channel.BUFFERED)
    doThework(channel)
    return channel.asFlow()
}


/**
* Does some work in background thread
*/
fun doThework(channel: BroadcastChannel) {

    SomeSope.launch {

        //Cretae a coroutine 
        channel.offer(ProcessStatus.Status1)
        channel.offer(ProcessStatus.Status2)
        channel.offer(ProcessStatus.Status3)
        channel.offer(ProcessStatus.Status4)

        channel.offer(rocessStatus.SUCCESS)
        channel.close()
    }
}

以上是我的代码的简化版本。

我想要做的是,让doWork() 等到所有值都被释放,最后根据最后一个ProcessStatus.SUCCESSProcessStatus.FAILURE 返回一个布尔值。

现在,上面代码的情况是,只要processWork() 返回流。 doWork() 调用包括single() 在内的所有操作员,因为工作仍在进行中 ProcessStatus.FAILURE 或 ProcessStatus.SUCCESS 仍然没有被释放,所以它给出了一个异常。

如何使doWork() return 语句等待并仅在流程完成时返回?


编辑 1:

原因,我必须使用频道是因为,这是 Android 代码的一部分,channel.offer() 实际上并不是上面示例中的新协同程序,而是从 Android BroadcastReceiver 调用.

由于流程很冷,我不希望用户离开 Activity 以阻止任务完成和通知。

【问题讨论】:

  • 您想使用频道的任何原因?你不能只使用 flowOn() 和 emit()s 并让 coroutines-lib 处理引擎盖下的通道内容吗? kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/…
  • @MathiasHenze 我通过问题中的编辑块回复了您的问题。
  • 您遇到什么异常?我希望这能奏效......
  • NoSuchElementException("Expected at least one element")
  • 我不完全理解这个问题,但似乎热流上的操作员链至少有一个复杂性:github.com/Kotlin/kotlinx.coroutines/issues/1758。所以尝试@Andrei Tanana 的建议首先将流程转换为列表似乎是个好主意

标签: android kotlin kotlin-coroutines kotlin-flow


【解决方案1】:

看起来您可以使用toList 方法在处理它们之前收集所有值:

suspend fun doWork(): Boolean {

    val processStatus = processWork().toList()

    return processStatus.filter { status ->
                status == ProcessStatus.SUCCESS 
                || status == ProcessStatus.FAILURE
            }.map { filteredStatus ->
                filteredStatus == ProcessStatus.SUCCESS
            }.single()
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-06-16
    • 2013-01-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-14
    • 2016-09-08
    相关资源
    最近更新 更多