簡體   English   中英

Kotlin 中 coroutineScope 的生命周期是多少?

[英]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,")
}
  1. 您不應該在任何協程應用程序中使用 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元素不提供取消它的功能。

  1. ViewModelScope 一直運行到您的應用程序被銷毀,更多信息和生命周期圖表在這里 如果您想運行一些非常重要的任務,請使用其他調度程序。

  2. 是的,代碼 A+ 完全正確

PS:你不應該在協程應用程序中實現runBlocking,它的默認實現只是事件循環。

runBlocking 是橋接同步和異步代碼的方式

主 function 的更好實現應該是:

suspend fun main() = coroutineScope {
    // code here
}

它在 CommonPool 上運行,如果它掛起另一個協程可以重用同一個線程。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM