英文:
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")
}
})
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论