簡體   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