Как получить результат от ответа внутри метода? - PullRequest
0 голосов
/ 16 июня 2020

Я новый разработчик android, как мне получить результат из этого фрагмента, какой способ существует, потому что он ничего не возвращает, потому что я добавляю элемент внутри 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
    }
}

Ответы [ 2 ]

0 голосов
/ 16 июня 2020

Вы можете дать своей функции параметр обратного вызова, который вызывается при получении ответа. И у вас не должно быть списка ввода в этом случае, потому что, если у вас есть несколько источников, изменяющих его в непредсказуемые моменты в будущем, его будет сложно отслеживать.

Функция может выглядеть так:

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
}

Альтернативой является использование сопрограмм, которые позволяют выполнять асинхронные действия без обратных вызовов. Кто-то уже создал библиотеку, которая позволяет использовать запросы 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 закрывается во время обработки запроса, она будет автоматически отменена, а ссылки на вашу Activity будут удалены, чтобы сборщик мусора мог освободить вашу Activity.

0 голосов
/ 16 июня 2020

Функция onResponse () вызывается только в том случае, если HTTP-ответ успешно возвращен удаленным сервером. Поскольку этот ответ не происходит сразу, вы не можете сразу использовать результат в своем коде. Что вы можете сделать, так это использовать переменные ViewModel и LiveData и добавить значения к этой переменной в 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)
    }
})

}

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...