Kotlin - OkHttp - возврат с onResponse - PullRequest
0 голосов
/ 21 января 2019

Я новичок в разработке Android и пытаюсь получить данные json из DarkSky API, используя OkHttp и GSon.Проблема в том, что мне нужно как-то вернуть ответ от метода onResponse, но он всегда равен нулю.

Вот мой код:

class DarkSky : Callback {

    private var url: String? = null
    private var forecast: Forecast? = null

    fun fetchJson(lat: Double, long: Double): Forecast? {
        this.url = "${Constants.DARK_SKY_BASE_URL}/${Constants.DARK_SKY_KEY}/$lat,$long?exclude=hourly,flags,offset"

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

        val client = OkHttpClient()
        client.newCall(request).enqueue(this)


        return this.forecast // when I debug this its NULL

    }


    override fun onFailure(call: Call, e: IOException) {
        println("error")
    }

    override fun onResponse(call: Call, response: Response) {

        if (response.isSuccessful) {
            val body = response.body()?.string()

            val gson = GsonBuilder().create()
            val forecast = gson.fromJson(body, Forecast::class.java)

            parse(forecast)
        }
    }

    private fun parse(response: Forecast) {
        this.forecast = response  //when I debug this, it contains data I need.
    }

}

РЕДАКТИРОВАТЬ:

Сделано, чтобы он работал с BlockingQueue,Но не знаю.Это хорошая идея?

class DarkSky {

    private var url: String? = null
    private var forecast: Forecast? = null

    fun fetchJson(lat: Double, long: Double): ArrayBlockingQueue<Forecast>? {
        this.url = "${Constants.DARK_SKY_BASE_URL}/${Constants.DARK_SKY_KEY}/$lat,$long?exclude=hourly,flags,offset"

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

        val blockingQueue: ArrayBlockingQueue<Forecast> = ArrayBlockingQueue(1) // <<<

        val client = OkHttpClient()
        client.newCall(request).enqueue(object : Callback {
            override fun onFailure(call: Call, e: IOException) {
                println("error")
            }

            override fun onResponse(call: Call, response: Response) {

                if (response.isSuccessful) {
                    val body = response.body()?.string()

                    val gson = GsonBuilder().create()
                    val forecast = gson.fromJson(body, Forecast::class.java)

                    blockingQueue.add(forecast) // <<<
                }
            }
        })

        return blockingQueue
    }

}

Не хочу учиться плохим практикам.

1 Ответ

0 голосов
/ 21 января 2019

Это потому, что

client.newCall(request).enqueue(this)

будет выполняться асинхронно в фоновом потоке.Таким образом, к тому времени, когда вы возвращаетесь, ему фактически не присваивается значение.

Решение:

Возможно, вам нужно передать объект класса, которыйсоответствует определенному интерфейсу и вызывает метод этого интерфейса.

Вот изменения, которые вам нужно сделать

class DarkSky : CallBack {

    private var url: String? = null
    private var forecast: Forecast? = null
    private var onRequestCompleteListener : OnRequestCompleteListener? =null

    fun fetchJson(lat: Double, long: Double,callback : OnRequestCompleteListener) {
        this.onRequestCompleteListener = callback
        this.url = "${Constants.DARK_SKY_BASE_URL}/${Constants.DARK_SKY_KEY}/$lat,$long?exclude=hourly,flags,offset"

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

        val client = OkHttpClient()
        client.newCall(request).enqueue(this)

    }


    override fun onFailure(call: Call, e: IOException) {
        onRequestCompleteListener?.onError()
        println("error")
    }

    override fun onResponse(call: Call, response: Response) {

        if (response.isSuccessful) {
            val body = response.body()?.string()

            val gson = GsonBuilder().create()
            val forecast = gson.fromJson(body, Forecast::class.java)

            parse(forecast)
        }
        onRequestCompleteListener?.onSuccess(forecast)
    }

    private fun parse(response: Forecast) {
        this.forecast = response  //when I debug this, it contains data I need.
    }

}


interface OnRequestCompleteListener{
    fun onSuccess(forcast :Forecast)
    fun onError()
}
...