【问题标题】:How to get result from response inside method?如何从方法内部的响应中获取结果?
【发布时间】:2020-06-16 17:25:08
【问题描述】:

我是新的 android 开发人员,我如何从这个 sn-p 中获取结果,存在什么方式,因为它不返回任何内容,因为我在 onResponse 中添加元素,但只使用 kotlin 模块:

private fun foo(list: ArrayList<CurrencyModel> = ArrayList()): ArrayList<CurrencyModel> {

        val request = Request.Builder().url(BASE_URL_YESTERDAY).build()

        val client = OkHttpClient()
        client.newCall(request).enqueue(object : Callback {

            override fun onFailure(call: Call, e: IOException) {

            }

            override fun onResponse(call: Call, response: Response) {
                val body = response.body?.string()
                val data = Gson().fromJson(body, Currencies::class.java)
                list.add(CurrencyModel("USD", data.rates.USD, 0.0))
                list.add(CurrencyModel("SEK", data.rates.SEK, 0.0))
                list.add(CurrencyModel("EUR", data.rates.EUR, 0.0))
            }
        })
        return list
    }
}

【问题讨论】:

  • 您不能从调用它的函数返回异步调用的结果,因为结果会在该函数已经返回之后的某个时间出现。你可以把它变成一个挂起函数并从协程中调用它,或者你可以给这个函数一个回调参数,它将在onResponse中调用,你调用这个函数的代码可以响应回调中的结果。
  • @Tenfour04 谢谢你的回答。你能举个例子吗?那会很酷
  • 我觉得我以前在这里回答过这个问题,但我找不到它。等一下。

标签: android kotlin gson


【解决方案1】:

您可以为函数提供一个回调参数,该参数在收到响应时调用。在这种情况下,您不应该有输入列表,因为如果您有多个来源在未来不可预测的时刻对其进行修改,则将难以跟踪。

函数可能如下所示:

private fun getCurrencyModels(callback: (ArrayList<CurrencyModel>) {

    val request = Request.Builder().url(BASE_URL_YESTERDAY).build()

    val client = OkHttpClient()
    client.newCall(request).enqueue(object : Callback {

        override fun onFailure(call: Call, e: IOException) {

        }

        override fun onResponse(call: Call, response: Response) {
            val body = response.body?.string()
            val data = Gson().fromJson(body, Currencies::class.java)
            val list = arrayListOf(
                CurrencyModel("USD", data.rates.USD, 0.0)),
                CurrencyModel("SEK", data.rates.SEK, 0.0)),
                CurrencyModel("EUR", data.rates.EUR, 0.0))
            )
            callback(list)
        }
    })
}

然后使用它:

getCurrencyModels { modelsList ->
    // do something with modelsList when it arrives
}

另一种方法是使用协程,它允许您在没有回调的情况下执行异步操作。有人已经创建了一个库,可以让你在协程here 中使用 OkHttp 请求。你可以把你的函数写成这样的挂起函数:

private suspend fun getCurrencyModels(): ArrayList<CurrencyModel> {

    val request = Request.Builder().url(BASE_URL_YESTERDAY).build()
    val client = OkHttpClient()
    val response = client.newCall(request).await()
    val body = response.body?.string()
    val data = Gson().fromJson(body, Currencies::class.java)
    return arrayListOf(
        CurrencyModel("USD", data.rates.USD, 0.0)),
        CurrencyModel("SEK", data.rates.SEK, 0.0)),
        CurrencyModel("EUR", data.rates.EUR, 0.0))
    )
}

然后像这样使用它:

lifecycleScope.launch {
    try {
        val currencyModels = getCurrencyModels()
        // do something with currencyModels
    } catch (e: IOException) {
        // request failed
    }
}

当您的异步调用超过您的 Activity 或 Fragment 时,协程可以很容易地避免内存泄漏。在这种情况下,如果您的 Activity 在请求进行时关闭,它将自动取消,并且对您的 Activity 的引用将被删除,以便垃圾收集器可以释放您的 Activity。

【讨论】:

  • 我尝试使用第二种变体,但 await() 会发出红色光 :(
  • 实现 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.7'
  • 你还需要我提到的第三方库implementation 'ru.gildor.coroutines:kotlin-coroutines-okhttp:1.0'
  • 我的错,我在努力,老板
  • 哇哦,老板,你救了我的命!谢谢你的回答和解释。 100/5 星。
【解决方案2】:

onResponse() 函数仅在远程服务器成功返回 HTTP 响应时调用。由于此响应不会立即发生,因此您不能立即在代码中使用结果。您可以做的是使用ViewModelLiveData 变量并将值添加到onResponse() 中的该变量。比如:

private fun foo(list: ArrayList<CurrencyModel> = ArrayList()) {

val request = Request.Builder().url(BASE_URL_YESTERDAY).build()

val client = OkHttpClient()
client.newCall(request).enqueue(object : Callback {

    override fun onFailure(call: Call, e: IOException) {

    }

    override fun onResponse(call: Call, response: Response) {
        val body = response.body?.string()
        val data = Gson().fromJson(body, Currencies::class.java)
        val list: ArrayList<CurrencyModel> = arrayListOf()
        list.add(CurrencyModel("USD", data.rates.USD, 0.0))
        list.add(CurrencyModel("SEK", data.rates.SEK, 0.0))
        list.add(CurrencyModel("EUR", data.rates.EUR, 0.0))
        viewModel.list.postValue(list)
    }
})

}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-06-04
    • 2018-04-24
    • 2018-01-30
    • 1970-01-01
    • 2015-03-25
    • 2017-09-16
    • 2012-06-08
    相关资源
    最近更新 更多