![](/img/trans.png)
[英]Difference between CoroutineScope and coroutineScope in Kotlin
[英]What is the lifetime of coroutineScope in Kotlin?
代碼 A 來自https://github.com/android/architecture-samples的項目架構示例
1:我不知道function activateTask(task: Task)
是否需要像Code B 一樣用runBlocking
包裹。如果DefaultTasksRepository
的object 被快速銷毀,恐怕activateTask(task: Task)
可能無法運行.
2:通常我在ViewModel.viewModelScope
中運行協程,我不知道在我完成應用程序時ViewModel.viewModelScope
是否會被銷毀,以及在ViewModel.viewModelScope
中運行的協程是否也會被銷毀。 如果是這樣,我認為會很糟糕,一些長時間的協程,例如向遠程服務器寫入數據將被取消。
3:還有,代碼A中的function activateTask
是一個協程function,它可以調用另一個協程function是正確的,所以我認為代碼A+直接?
代碼 A
import kotlinx.coroutines.coroutineScope
...
class DefaultTasksRepository(
private val tasksRemoteDataSource: TasksDataSource,
private val tasksLocalDataSource: TasksDataSource,
private val ioDispatcher: CoroutineDispatcher = Dispatchers.IO
) : TasksRepository {
...
override suspend fun activateTask(task: Task) = withContext<Unit>(ioDispatcher) {
coroutineScope {
launch { tasksRemoteDataSource.activateTask(task) }
launch { tasksLocalDataSource.activateTask(task) }
}
}
override suspend fun clearCompletedTasks() {
coroutineScope {
launch { tasksRemoteDataSource.clearCompletedTasks() }
launch { tasksLocalDataSource.clearCompletedTasks() }
}
}
...
}
代碼 A+
import kotlinx.coroutines.coroutineScope
...
class DefaultTasksRepository(
private val tasksRemoteDataSource: TasksDataSource,
private val tasksLocalDataSource: TasksDataSource,
private val ioDispatcher: CoroutineDispatcher = Dispatchers.IO
) : TasksRepository {
...
override suspend fun activateTask(task: Task) = withContext<Unit>(ioDispatcher) {
tasksRemoteDataSource.activateTask(task)
tasksLocalDataSource.activateTask(task)
}
override suspend fun clearCompletedTasks() {
tasksRemoteDataSource.clearCompletedTasks()
tasksLocalDataSource.clearCompletedTasks()
}
...
}
代碼 B
fun main() = runBlocking {
launch {
delay(1000L)
println("World!")
}
println("Hello,")
}
您不應該在任何協程應用程序中使用 runBlocking,它會阻塞線程。
如果你真的想讓activateTask
不可取消,那么標准庫中已經有一個NonCancellable的工廠實現
並且您不應該在 withContext 中使用 coroutineScope 包裝器,因為新創建的 CoroutineScope 和新作業已經作為接收者在withContext
中傳遞。
像這樣實現您的 activateTask:
override suspend fun activateTask(task: Task) = withContext<Unit>(ioDispatcher + NonCancellable) {
launch { tasksRemoteDataSource.activateTask(task) }
launch { tasksLocalDataSource.activateTask(task) }
}
通過這種方式,它將在 IODispatcher 上調用,但不能取消,因為生成的上下文的Job
元素不提供取消它的功能。
ViewModelScope 一直運行到您的應用程序被銷毀,更多信息和生命周期圖表在這里。 如果您想運行一些非常重要的任務,請使用其他調度程序。
是的,代碼 A+ 完全正確
PS:你不應該在協程應用程序中實現runBlocking,它的默認實現只是事件循環。
runBlocking 是橋接同步和異步代碼的方式
主 function 的更好實現應該是:
suspend fun main() = coroutineScope {
// code here
}
它在 CommonPool 上運行,如果它掛起另一個協程可以重用同一個線程。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.