Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/kotlin/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 科特林coroutineScope的寿命是多少?_Android_Kotlin_Kotlin Coroutines - Fatal编程技术网

Android 科特林coroutineScope的寿命是多少?

Android 科特林coroutineScope的寿命是多少?,android,kotlin,kotlin-coroutines,Android,Kotlin,Kotlin Coroutines,代码A来自于 1:我不知道函数activateTask(task:task)是否需要像代码B一样用runBlocking包装。如果DefaultTasksRepository的对象很快被销毁,我担心activateTask(task:task)可能无法运行 2:通常我在ViewModel.viewModelScope中运行协同程序,我不知道当我完成应用程序时,ViewModel.viewModelScope中运行的协同程序是否也会被销毁。如果是这样的话,我认为这将是不好的,一些长时间的协同工作,

代码A来自于

1:我不知道函数
activateTask(task:task)
是否需要像代码B一样用
runBlocking
包装。如果
DefaultTasksRepository
的对象很快被销毁,我担心
activateTask(task:task)
可能无法运行

2:通常我在
ViewModel.viewModelScope
中运行协同程序,我不知道当我完成应用程序时,
ViewModel.viewModelScope
中运行的协同程序是否也会被销毁。如果是这样的话,我认为这将是不好的,一些长时间的协同工作,例如向远程服务器写入数据,将被取消

3:而且,代码A中的函数
activateTask
是一个协同路由函数,它可以直接调用另一个协同路由函数,所以我认为代码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() }
        }
    }
   ...
}
  • 您不应该在任何协程应用程序中使用runBlocking,它会阻塞线程

    如果您确实想使
    activateTask
    不可取消,则stdlib中已经有了的工厂实现

    而且您不应该在withContext中使用coroutineScope包装器,因为新创建的coroutineScope以及新作业已经作为接收者在
    withContext
    中传递

    按如下方式实施activateTask:

  • override suspend-fun-activateTask(任务:任务)=withContext(Iiodispatcher+不可取消){
    启动{tasksRemoteDataSource.activateTask(任务)}
    启动{tasksLocalDataSource.activateTask(任务)}
    }
    
    这样,它将在Iiodispatcher上被调用,但不会被取消,因为结果上下文的
    作业
    元素不提供取消它的功能

  • ViewModelScope将一直运行,直到应用程序被销毁,并显示更多信息和生命周期图表。如果您想运行一些非常重要的任务,那么请使用其他调度程序

  • 是代码A+完全正确

  • PS:您不应该在协同路由应用程序中实现runBlocking,它的默认实现只是事件循环

    runBlocking是连接同步和异步代码的方法

    更好地实现主要功能应该是:

    suspend fun main()=coroutineScope{
    //代码在这里
    }
    

    它在CommonPool上运行,如果它挂起另一个协同程序,则可以重用同一个线程。

    如果您对协同程序及其组件感到困惑,我建议您先阅读关于协同程序的第一件事,谢谢!代码A和代码A+之间有什么不同?我认为代码A就像异步的,代码A+就像同步的,对吗?@HelloCW在activateTask中没有区别,只是嵌套的coroutineScope调用只是覆盖了coroutineContext中的作业元素。在
    clearCompletedTasks
    上,coroutineScope从调用它的任何位置继承上下文,并在该上下文中启动它们(如果上下文调度器支持多线程环境,则同时启动),没有理由对清除等非常小的任务执行此操作。
    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()             
       }
       ...
    }
    
    fun main() = runBlocking { 
        launch { 
          delay(1000L)
          println("World!")
        }
        println("Hello,")
    }