我正在使用协程编写一个应用程序(下面的代码已大大简化)。最近,我看了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()
}
所以我有几个问题:
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#getRssChannel
,
getAllChannels
,fetchChannel
)?然后如何在saveChannel
中使用它?UseCase
包装到
Repository#getRssChannel
功能是为了使所有生成的都挂起
成为后者的孩子吗?coroutineScope
的扩展名吗?答案 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
扩展功能的候选者。