应该使用CoroutineScope的扩展功能或暂停功能

时间:2018-12-13 22:08:23

标签: kotlin coroutine kotlinx.coroutines

我正在使用协程编写一个应用程序(下面的代码已大大简化)。最近,我看了Coroutines in Practice的谈话,有些困惑。原来,我不知道何时使用latency | Total ------------------------------------- Fast | 11 Normal | 14 Elevated | 3 High | 1 的扩展功能以及何时使用暂停功能。

我有一个实现CoroutineScope的介体(Presenter / ViewModel / Controller / etc):

CoroutineScope

业务逻辑(Interactor / UseCase):

class UiMediator : CoroutineScope {
    private val lifecycleJob: Job = Job()
    override val coroutineContext = lifecycleJob + CoroutineDispatchersProvider.MAIN
    // cancel parent Job somewhere

    fun getChannel() {
        launch {
            val channel = useCase.execute()
            view.show(channel)
        }
    }
}

和一个存储库

class UseCase {
    suspend fun execute(): RssChannel = repository.getRssChannel()
}

所以我有几个问题:

  1. 我应该将class Repository { suspend fun getRssChannel(): RssChannel { // `getAllChannels` is a suspending fun that uses `withContext(IO)` val channels = localStore.getAllChannels() if (channels.isNotEmpty()) { return channels[0] } // `fetchChannel` is a suspending fun that uses `suspendCancellableCoroutine` // `saveChannel` is a suspending fun that uses `withContext(IO)` return remoteStore.fetchChannel() .also { localStore.saveChannel(it) } } } 声明为CoroutineScope的扩展功能(因为 它产生了新的暂停功能:Repository#getRssChannelgetAllChannelsfetchChannel)?然后如何在saveChannel中使用它?
  2. 我应该将UseCase包装到 Repository#getRssChannel功能是为了使所有生成的都挂起 成为后者的孩子吗?
  3. 或者也许已经很好了,我什么也不要改变。何时 声明一个函数作为coroutineScope的扩展名吗?

2 个答案:

答案 0 :(得分:2)

一个暂停函数应该在完成任务后返回,它执行一些操作,可能会花一些时间而不阻塞UI,并在完成后返回。

CoroutineScope扩展功能用于即发即弃的场景,您称之为它,它会生成一个协程并立即返回,同时任务继续执行。

答案 1 :(得分:2)

问题1的答案:

否,您不应Repository#getRssChannel声明为CoroutineScope的扩展功能,因为您仅调用暂停功能而不启动(launch / {{ 1}})新工作。正如@Francesc所解释的,async的扩展功能只能启动新作业,而不能立即返回结果,并且不应单独声明为CoroutineScope

问题2的答案:

否,您应该suspend包装到Repository#getRssChannel中。只有以这种方法开始(CoroutineScope / launch)新协程时,包装才有意义。新作业将是当前作业的子作业,并且仅在所有并行作业完成后才返回外部方法。在您的情况下,您需要依次调用其他挂起的协程,因此不需要新的作用域。

问题3的答案:

是的,您可以保留代码。如果您一次又需要async的功能,那么该方法将是UiMediator#getChannel扩展功能的候选者。