标签: coroutinescope

如何将协程直接分派到 JVM 上的主线程?

我正在为 jvm 设置一个基于 kotlin 协程的网络框架。Client 和 Server 类实现 CoroutineScope,并且 coroutinecontext 的覆盖是 Dispatchers.IO,因为我非常确定这是用于这种情况的正确 Dispatcher。但是,我希望在主线程上处理读取数据包,或者至少提供该选项。在没有阅读文档的情况下,我使用了 Dispatchers.Main,我现在意识到它是针对 android UI 线程的。是否有一个调度程序可以用来让协程在主线程上运行?如果没有,我该如何制作呢?

我查看了 kotlin 文档,了解如何创建基于单个线程的调度程序,但除了创建新线程的 newSingleThreadContext 之外,我找不到任何内容。我还发现可以从 java 执行器创建调度程序,但我仍然不确定如何将其限制为已经存在的线程。

class AbstractNetworkComponent : CoroutineScope {
    private val packetProcessor = PacketProcessor()
    private val job = Job()
    override val coroutineContext = job + Dispatchers.IO
}

class PacketProcessor : CoroutineScope {

    private val job = Job()
    override val coroutineContext = job + Dispatchers.Main //Android only!
    private val packetHandlers = mutableMapOf<Opcode, PacketHandlerFunc>()

    fun handlePacket(opcode: Opcode, packet: ReceivablePacket, networker: Writable) { …
Run Code Online (Sandbox Code Playgroud)

multithreading kotlin kotlin-coroutines coroutinescope

6
推荐指数
1
解决办法
3979
查看次数

如何在另一个函数中运行一个挂起函数而不等待其结果?

我有一个场景,我的代码必须发送 api 调用并继续其工作(其中包含另一个 api 调用),而不等待第一次调用的结果。

现在我在我的视图模型中执行此操作

fun showItem(id:Int) {
   launch{
       repo.markItemRead(id)
   }
   launch {
       try {
           val item = repo.getItemById(id).getOrThrow
           commands.postValue(ShowItemCommand(item))
       } catch (t:Throwable) {
           commands.postValue(ShowError(R.string.error_retrieve_item))
           repo.logError(t)
       }
   }
}
Run Code Online (Sandbox Code Playgroud)

这调用了具有这两个功能的存储库

suspend fun markItemRead(id) {
    try {
        service.markItemAsRead(id)
    } catch(ignored:Throwable) {
    }
}

suspend fun getItemById(id) : Result<ItemData> {
    return try {
       val response : ItemEntity = service.getItemById(id)
       val item  = response.toData()
       Result.Success(item)
    } catch (t:Throwable) {
        Result.Failure(t)
    }
}
Run Code Online (Sandbox Code Playgroud)

如果存储库完成所有这些工作,我会更喜欢它,因为每次都必须遵循另一项工作。

不幸的是,当我尝试在我的存储库中执行类似的操作时:

suspend fun getItemById(id:Int) : Result<ItemData> {
    try { …
Run Code Online (Sandbox Code Playgroud)

android coroutine kotlin kotlin-coroutines coroutinescope

6
推荐指数
1
解决办法
5102
查看次数

Android CoroutineScope 完成后自动取消

我想知道coroutineScope工作完成后是否会自动取消。coroutineScope假设我在自定义类中创建一个而不是 ViewModel类或Fragment / Activity类:

class MyClass {
    private val backgroundScope = CoroutineScope(Dispatchers.Default)

    fun doSomething() = backgroundScope.launch {
        //do background work
    }
}
Run Code Online (Sandbox Code Playgroud)

那么,后台工作完成后,会backgroundScope自动取消吗?

android kotlin kotlin-coroutines android-threading coroutinescope

6
推荐指数
2
解决办法
3591
查看次数

使用 GlobalScope.launch 和 CoroutineScope().launch 启动协程有区别吗?

在 Kotlin 中启动协程有多种方法。我发现了几个使用GlobalScope和的例子CoroutineScope。但后一个是在启动协程时直接创建的:

  1. 使用GlobalScope

    fun loadConfiguration() {
        GlobalScope.launch(Dispatchers.Main) {
           val config = fetchConfigFromServer() // network request
           updateConfiguration(config)
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)
  2. 使用CoroutineScope实例,在启动协程时直接创建:

    fun loadConfiguration() {
        CoroutineScope(Dispatchers.Main).launch {
            val config = fetchConfigFromServer() // network request
            updateConfiguration(config)
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)

在这种情况下,这两种方法有区别吗?

第二种情况不是违反了结构化并发的原则吗?

android kotlin kotlin-coroutines coroutinescope structured-concurrency

6
推荐指数
1
解决办法
9684
查看次数

Local CoroutineScope().launch { },创建的协程作用域在内存中存活多久?

我无法理解内存管理如何在 Android 上与本地创建的协程一起工作。这是一些代码:

 init {
    CoroutineScope(Dispatchers.Default).launch {
        val result = workerA.runSuspended(paramA)
        liveDataA.postValue(result)
    }
}
Run Code Online (Sandbox Code Playgroud)

对于短暂的挂起函数调用,我想启动一次协程,然后我不再需要作用域。我知道这样写时不能取消范围。但我的主要问题是:

  1. 工作完成后会发生什么?coroutineScope 是否被垃圾回收?
  2. 范围是否保证在作业完成之前保持活动状态?
  3. 如果 runSuspished 一直卡住会发生什么?如果父对象被垃圾回收,会不会出现内存泄漏?

android kotlin kotlin-coroutines coroutinescope

6
推荐指数
0
解决办法
455
查看次数

在runBlocking中使用coroutineScope有什么效果?

在 kotlin coroutines doc 中,它解释了“runBlocking 和 coroutineScope 之间的区别”:

范围生成器

除了不同构建器提供的协程作用域之外,还可以使用 coroutineScope 构建器来声明您自己的作用域。它创建了一个协程范围,并且在所有启动的子项完成之前不会完成。The main difference between runBlocking and coroutineScope is that the latter does not block the current thread while waiting for all children to complete.

我不太明白,示例代码显示

import kotlinx.coroutines.*

fun main() = runBlocking { // this: CoroutineScope
launch { 
    delay(200L)
    println("+++Task from runBlocking")
}

coroutineScope { // Creates a coroutine scope
    launch {
        delay(500L) 
        println("+++Task from nested launch")
    }

    delay(100L)
    println("+++ Task from coroutine scope") // This line …
Run Code Online (Sandbox Code Playgroud)

kotlin kotlin-coroutines coroutinescope

5
推荐指数
2
解决办法
1118
查看次数

在 ViewModel 与 LifeCycleOwner 中启动协程(活动/片段)

是在 ViewModel 中启动协程更好,还是用suspend修饰符标记 ViewModel 函数并在 Activity/fragment 本身中启动协程更好?

在 ViewModel 中启动:

class MainViewModel: ViewModel() {
  fun addNewItem(item: Item) {
    viewModelScope.launch {
      // Add the item to database
    }
  }
}
Run Code Online (Sandbox Code Playgroud)
class ItemsFragment: Fragment() {
  fun onButtonClick() {
    viewModel.addNewItem(Item())
  }
}
Run Code Online (Sandbox Code Playgroud)

在 LifeCycleOwner 中启动:

class MainViewModel: ViewModel() {
  suspend fun addNewItem(item: Item) {
    // Add the item to database
  }
}
Run Code Online (Sandbox Code Playgroud)
class ItemsFragment: Fragment() {
  fun onButtonClick() {
    lifecycleScope.launchWhenStarted {
      viewModel.addNewItem(Item())
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

android kotlin android-viewmodel kotlin-coroutines coroutinescope

5
推荐指数
1
解决办法
1607
查看次数

无法访问“kotlinx.coroutines.CoroutineScope”,它是“androidx.lifecycle.LifecycleCoroutineScope”的超类型

尝试使用 room api 并且必须处理异步任务,你知道为什么。我选择了 kotlin 协程和 androidx.lifecycle。尝试编写一些代码并在 IDE 中显示 2 个错误

无法访问“kotlinx.coroutines.CoroutineScope”,它是“androidx.lifecycle.LifecycleCoroutineScope”的超类型。检查模块类路径是否缺少或冲突的依赖项无法访问类“kotlinx.coroutines.Job”。检查模块类路径是否存在缺少或冲突的依赖项 错误

这是我的 gradle 模块

plugins {
    id 'com.android.application'
    id 'kotlin-android'
    id 'kotlin-kapt'

}

android {
    compileSdk 31

    defaultConfig {
        applicationId "com.jacksafblaze.sqlitedemo"
        minSdk 21
        targetSdk 31
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }
    buildFeatures{
        viewBinding true
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
    kotlinOptions {
        jvmTarget = '1.8'
    }
}

dependencies {
    implementation "androidx.room:room-ktx:2.3.0"
    implementation "androidx.room:room-runtime:2.3.0"
    kapt …
Run Code Online (Sandbox Code Playgroud)

kotlin android-studio android-gradle-plugin kotlin-coroutines coroutinescope

5
推荐指数
1
解决办法
3727
查看次数

launch {whenStarted {} } 和 launchWhenStarted {} 完全相同吗?

下面的完全一样吗?

\n
lifecycleScope.launch {\n\xc2\xa0   whenStarted { \n        // Do something\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

\n
lifecycleScope.launchWhenStarted {\n    // Do something\n}\n
Run Code Online (Sandbox Code Playgroud)\n

或者它们确实有一些不同的目的,因此提供了这两个 API?

\n

android coroutine activity-lifecycle coroutinescope

5
推荐指数
1
解决办法
2575
查看次数

在另一个协程内部时协程 launch()

我有以下代码(伪代码)

fun onMapReady()
{
    //do some stuff on current thread (main thread)

    //get data from server
    GlobalScope.launch(Dispatchers.IO){

        getDataFromServer { result->

            //update UI on main thread
            launch(Dispatchers.Main){
                updateUI(result) //BREAKPOINT HERE NEVER CALLED
            }
        }

    }
}
Run Code Online (Sandbox Code Playgroud)

正如评论所述,代码永远不会进入协程调度到主队列。但是,如果我明确使用GlobalScope.launch(Dispatchers.Main)而不是仅仅使用以下内容,则以下内容有效launch(Dispatchers.Main)

fun onMapReady()
{
    //do some stuff on current thread (main thread)

    //get data from server
    GlobalScope.launch(Dispatchers.IO){

        getDataFromServer { result->

            //update UI on main thread
            GlobalScope.launch(Dispatchers.Main){
                updateUI(result) //BREAKPOINT HERE IS CALLED
            }
        }

    }
}
Run Code Online (Sandbox Code Playgroud)

为什么第一种方法不起作用?

kotlin kotlin-coroutines coroutinescope

4
推荐指数
1
解决办法
4444
查看次数