我为什么在尝试将OkHttp响应写入Kotlin的.json文件时收到’closed’异常?

huangapple go评论66阅读模式
英文:

Why am I getting a 'closed' exception when trying to write OkHttp response to .json file in Kotlin?

问题

The problematic line is osw.write(response.body()?.string()). 我希望有人可以知道问题可能是什么,因为我已经卡在这里很长时间了,找不出解决办法。 预先致以感谢和亲切的问候。

英文:

I am trying to make a Currency Conversion App in Kotlin and have a problem with updating my values. The connection works fine but I cannnot write it into an .json file.
Here is my Code:

        val request = Request.Builder().url(url).header("apikey", key).build()

        val client = OkHttpClient()
        client.newCall(request).enqueue(object : Callback {
            override fun onFailure(call: Call, e: IOException) {}
            override fun onResponse(call: Call, response: Response) {
                println(response.body()?.string())
                val date = LocalDate.now()
                val osw = OutputStreamWriter(openFileOutput("$date.json", MODE_PRIVATE))
                osw.write(response.body()?.string())
                println("finished")
            }
        })
    }
Here is the Error: 
E/AndroidRuntime: FATAL EXCEPTION: OkHttp Dispatcher
    Process: com.example.appdevelopment_assignment_7, PID: 6787
    java.lang.IllegalStateException: closed
        at okio.RealBufferedSource.rangeEquals(RealBufferedSource.java:398)
        at okio.RealBufferedSource.rangeEquals(RealBufferedSource.java:392)
        at okhttp3.internal.Util.bomAwareCharset(Util.java:431)
        at okhttp3.ResponseBody.string(ResponseBody.java:174)
        at com.example.appdevelopment_assignment_7.ComplexCurrencyConversionActivity$update$1.onResponse(ComplexCurrencyConversionActivity.kt:36)
        at okhttp3.RealCall$AsyncCall.execute(RealCall.java:141)
        at okhttp3.internal.NamedRunnable.run(NamedRunnable.java:32)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1137)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:637)
        at java.lang.Thread.run(Thread.java:1012)

The problematic line is osw.write(response.body()?.string()). I hope someone might have an idea what could be the problem because I'm stuck here quite a while and couldn't figure it out.

Thanks in advance and Kind regards

答案1

得分: 1

你只能在 ResponseBody 上调用 string() 一次,因为 okhttp 从流中读取数据并不保留引用,读取后它会关闭流!你需要调用 string() 将值存储在变量中,然后多次使用它。

val request = Request.Builder().url(url).header("apikey", key).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 responseBody = response.body()?.string() // 在调用 string() 后流已关闭
        println(responseBody)
        val date = LocalDate.now()
        val osw = OutputStreamWriter(openFileOutput("$date.json", MODE_PRIVATE))
        osw.write(responseBody)
        println("完成")
    }
})
}
英文:

You can call string() on ResponseBody only once, as okhttp reads the data from stream and does not hold reference, it throws closed as it has already closed the stream post reading! You need to call string() and store value inside a variable and then use it multiple times.

val request = Request.Builder().url(url).header("apikey", key).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 responseBody = response.body()?.string() // stream closed after invoking string()
        println(responseBody)
        val date = LocalDate.now()
        val osw = OutputStreamWriter(openFileOutput("$date.json", MODE_PRIVATE))
        osw.write(responseBody)
        println("finished")
    }
})
}

huangapple
  • 本文由 发表于 2023年5月20日 21:29:27
  • 转载请务必保留本文链接:https://go.coder-hub.com/76295483.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定