kotlin - 应使用 CoroutineScope 的扩展函数或挂起函数

标签 kotlin coroutine kotlinx.coroutines

我正在使用协程编写一个应用程序(下面的代码已大大简化)。最近看了Coroutines in Practice说话有点糊涂了。原来我不知道什么时候使用 CoroutineScope 的扩展函数,什么时候使用挂起函数。

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

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()
}

还有一个存储库:

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) }
    }
}

所以我有几个问题:

  1. 我是否应该将 Repository#getRssChannel 声明为 CoroutineScope 的扩展函数(因为 它产生了新的暂停函数:getAllChannelsfetchChannel, saveChannel)?那么如何在 UseCase 中使用它呢?
  2. 我是否应该将 Repository#getRssChannel 包装到一个 coroutineScope 函数使所有生成的暂停 函数是后者的 child ?
  3. 或者也许它已经很好了,我什么都不应该改变。何时 然后将函数声明为 CoroutineScope 的扩展?

最佳答案

问题 1 的答案:

不,你不应该Repository#getRssChannel声明为CoroutineScope的扩展函数,因为你只调用挂起函数而不是启动( launch/async) 新作业。正如@Francesc 解释的那样,CoroutineScope 的扩展函数应该只开始新的工作,但不能立即返回结果,不应该声明为 suspend 本身。

问题 2 的答案:

不,您应该Repository#getRssChannel 包装到CoroutineScope 中。仅当您在此方法中启动 (launch/async) 新协程时,包装才有意义。新作业将是当前作业的子作业,外部方法只会在所有并行作业完成后返回。在您的情况下,您有其他暂停协程的顺序调用,并且不需要新的范围。

问题 3 的答案:

是的,您可以保留您的代码。如果您多次需要 UiMediator#getChannel 的功能,那么此方法将是 CoroutineScope 的扩展函数的候选方法。

关于kotlin - 应使用 CoroutineScope 的扩展函数或挂起函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53770772/

相关文章:

android - Kotlin:是否可以在函数中传递两个 'this'?

javascript - JavaScript 中纤程的客户端实现。

android-studio - 编译错误: "-Xcoroutines has no effect: coroutines are enabled anyway in 1.3 and beyond"

rest - 节流或限制 Kotlin CoRoutine 计数

android - 协程在取消时注销接收者

kotlin - 如何在 super 接口(interface)上调用被覆盖的函数?

java - 将 Kotlin 类转换为 Java

android - 访问 RecyclerViewAdapter 内的生命周期范围

c# - Unity定期设置PlayerPrefs数据

testing - Mockk:在协同程序中验证调用的方法