繁体   English   中英

Kotlin 协程没有同步运行

[英]Kotlin coroutine does not run synchronously

在我一直使用 corrutines 的所有情况下,到目前为止,它一直在同步执行它的“行”,这样我就能够在下一行代码中使用变量的结果。

我有调用服务器的 ImageRepository class,获取图像列表,一旦获得,就创建一个包含图像和相关信息的 json。

class ImageRepository {

    val API_IMAGES = "https://api.MY_API_IMAGES"

    suspend fun fetch (activity: AppCompatActivity) {

        activity.lifecycleScope.launch() {

            val imagesResponse = withContext(Dispatchers.IO) {
                getRequest(API_IMAGES)
            }

            if (imagesResponse != null) {
                val jsonWithImagesAndInfo = composeJsonWithImagesAndInfo(imagesResponse)

            } else {
                // TODO Warning to user
                Log.e(TAG, "Error: Get request returned no response")
            }

          ...// All the rest of code
        }
    }
}

嗯,suspend function 正确同步执行,它首先在 getRequest 中调用服务器,当有响应时,然后组成 JSON。到目前为止,一切顺利。

这是我的主要活动对“ImageRepository”暂停 function 的调用:

lifecycleScope.launch {
    val result = withContext(Dispatchers.IO) { neoRepository.fetch(this@MainActivity) }
    Log.i(TAG, "After suspend fun")
}

问题是,一执行就调用暂停function然后显示log,明显是空的。 它不会等待暂停 function 完成,然后显示日志。

为什么? 我究竟做错了什么?

我尝试了不同的 Dispatchers 等,但没有成功。

我感谢任何帮助。

谢谢并致以最诚挚的问候。

这是因为您正在从您的暂停 function 中并行启动另一个协程。与其在那里启动另一个协程,不如直接在您的暂停 function 中调用该启动的内容。

suspend function 就像普通的 function 一样,一条一条指令执行。 唯一的区别是它可以暂停,这意味着运行时环境可以决定暂停/暂停执行以执行其他工作,然后稍后恢复执行。

这是真的,除非你开始了一个你不应该做的异步操作。 您的提取操作应如下所示:

class ImageRepository {

    suspend fun fetch () {
        val imagesResponse = getRequest(API_IMAGES)

        if (imagesResponse != null) {
            val jsonWithImagesAndInfo = composeJsonWithImagesAndInfo(imagesResponse)
        } else {
            // TODO Warning to user
            Log.e(TAG, "Error: Get request returned no response")
        }
        ... // All the rest of code
    }

}

-> 就像常规的 function 一样。当然,您需要从协程中获取所有信息:

lifecycleScope.launch {
    val result = withContext(Dispatchers.IO) { neoRepository.fetch() }
    Log.i(TAG, "After suspend fun")
}

Google 建议将调度程序注入较低级别的类 ( https://developer.android.com/kotlin/coroutines/coroutines-best-practices ) 所以理想情况下你会这样做:

val neoRepository = ImageRepository(Dispatchers.IO)

lifecycleScope.launch {
    val result = neoRepository.fetch()
    Log.i(TAG, "After suspend fun")
}

class ImageRepository(private val dispatcher: Dispatcher) {

    suspend fun fetch () = withContext(dispatcher) {
        val imagesResponse = getRequest(API_IMAGES)

        if (imagesResponse != null) {
            val jsonWithImagesAndInfo = composeJsonWithImagesAndInfo(imagesResponse)
        } else {
            // TODO Warning to user
            Log.e(TAG, "Error: Get request returned no response")
        }
        ... // All the rest of code
    }

}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM