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



我正在使用协程编写一个应用程序(下面的代码大大简化了(。最近我看了《实践中的推论》的演讲,有点困惑。事实证明,我不知道何时使用CoroutineScope的扩展函数,何时使用挂起函数。

我有一个中介(Presenter/ViewModel/Controller/etc(,它实现了CoroutineScope:

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的扩展函数吗(因为它产生了新的挂起函数:CCD_ 3,fetchChannelsaveChannel(?那么我该如何在UseCase中使用它呢
  2. 我应该把Repository#getRssChannel包装成coroutineScope函数以使所有派生的挂起作为后者的孩子
  3. 或者可能已经很好了,我什么都不应该改变。何时那么,将函数声明为CoroutineScope的扩展

挂起函数在完成任务后应该返回,它执行一些东西,可能需要一些时间,同时不会阻塞UI,完成后返回。

CoroutineScope扩展函数适用于即发即弃场景,您调用它,它生成一个协程并立即返回,同时任务继续执行。

问题1的答案:

不,您不应该Repository#getRssChannel声明为CoroutineScope的扩展函数,因为您只调用挂起函数,而不启动(launch/async(新作业。正如@Francesc所解释的,CoroutineScope的扩展函数只能启动新的作业,但不能立即返回结果,也不应该自己声明为suspend

问题2的答案:

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

问题3的答案:

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

最新更新