[英]Kotlin Coroutine wait for Retrofit Response
我正在嘗試將 Android MVVM
模式與存儲庫 class 和Retrofit
用於網絡調用。 我有一個常見的問題是我無法讓協程等待網絡響應返回。
此方法在我的ViewModel
class 中:
private fun loadConfigModel() {
val model = runBlocking {
withContext(Dispatchers.IO) {
configModelRepository.getConfigFile()
}
}
configModel.value = model
}
在ConfigModelRepository
,我有這個:
suspend fun getConfigFile(): ConfigModel {
val configString = prefs.getString(
ConfigViewModel.CONFIG_SHARED_PREF_KEY, "") ?: ""
return if (configString.isEmpty() || isCacheExpired()) {
runBlocking { fetchConfig() }
} else {
postFromLocalCache(configString)
}
}
private suspend fun fetchConfig(): ConfigModel {
return suspendCoroutine { cont ->
dataService
.config() // <-- LAST LINE CALLED
.enqueue(object : Callback<ConfigModel> {
override fun onResponse(call: Call<ConfigModel>, response: Response<ConfigModel>) {
if (response.isSuccessful) {
response.body()?.let {
saveConfigResponseInSharedPreferences(it)
cont.resume(it)
}
} else {
cont.resume(ConfigModel(listOf(), listOf()))
}
}
override fun onFailure(call: Call<ConfigModel>, t: Throwable) {
Timber.e(t, "config fetch failed")
cont.resume(ConfigModel(listOf(), listOf()))
}
})
}
}
我的代碼一直運行到dataService.config()
。 它永遠不會進入onResponse
或onFailure
。 網絡調用正確地進行並返回(我可以使用 Charles 看到這一點),但協程似乎沒有在監聽回調。
所以,我的問題是通常的問題。 如何讓協程阻塞,以便它們等待來自Retrofit
的回調? 謝謝。
問題一定是response.body()
返回null
因為這是唯一缺少對cont.resume()
調用的情況。 確保在這種情況下也調用cont.resume()
並且您的代碼至少應該不會卡住。
但就像 CommonsWare 指出的那樣,更好的辦法是升級到 Retrofit 2.6.0 或更高版本並使用本機suspend
支持而不是滾動您自己的suspendCoroutine
邏輯。
您還應該完全停止使用runBlocking
。 在第一種情況下,改為launch(Dispatchers.Main)
協程並將configModel.value = model
移動到其中。 在第二種情況下,您可以刪除runBlocking
並直接調用fetchConfig()
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.