Mar*_*ers 7 json kotlin retrofit okhttp
我正在尝试在接收(流式传输/分块)时解析/处理 JSON 响应。但我无法让它发挥作用。当我收到 JSON 时,我只能在收到整个响应后才能处理它。
如果我使用静态文件下载测试相同的代码,则它可以正常工作。
改造:2.6.1 OkHTTP 3.12.0
当我下载 5MB 文件时,将立即显示“调用确定”通知,稍后显示“下载完成”。对于 JSON 文件,“调用确定”将需要一段时间。
Logger.info("Start download")
val response = fileApi.download5MBFile() // Streaming
val response = dataHubApi.download3MBJson() //Does not stream
val response = articleApi.download10MBJson() // Does not stream
if (response.isSuccessful) {
Logger.info("Call ok")
val input = response.body()?.byteStream()
val buffer = ByteArray(8192)
var size = 0
while (true) {
val read = input!!.read(buffer)
if (read == -1) {
break
}
size += read
//Logger.info("Progress: ${size/1024/1024}mb")
}
Logger.info("Download complete")
} else {
Logger.info("Call not ok")
}
Run Code Online (Sandbox Code Playgroud)
创建 API 的工厂方法都是相同的,如下所示:
fun create(): FileApi {
val logLevel = Level.HEADERS
val retrofit = Retrofit.Builder()
.baseUrl(URL)
.client(getOkHttpClient(logLevel))
.build()
return retrofit.create(FileApi::class.java)
}
private fun getOkHttpClient(logLevel: Level): OkHttpClient {
return OkHttpClient.Builder()
.readTimeout(60L, TimeUnit.SECONDS) // default retrofit value is 10sec
.build()
}
Run Code Online (Sandbox Code Playgroud)
并且所有的接口也都是相同的格式:
interface FileApi {
@GET("/5MB.zip")
@Streaming
suspend fun download5MB(): Response<ResponseBody>
}
Run Code Online (Sandbox Code Playgroud)
我还能做什么来流式传输 JSON?
如果它那么大,可能是因为它包含多个项目的列表,而不是一个或一小块元素。
[
{ item1 },
{ item2 },
...
]
Run Code Online (Sandbox Code Playgroud)
即使它是 firebase json 表示形式,您也会得到以下内容:
{
"key1": {element },
"key2": {element },
"key3": { element },
...
}
Run Code Online (Sandbox Code Playgroud)
如果您在解析完整的 json 时遇到困难,那么您很可能在将其保存到 kotlin 列表中时也会遇到一些麻烦,因此最好的办法是将其直接保存到数据库中,您可以在其中管理单个对象或页面稍后的对象。
因此,技巧是将 JSON 作为流式文本下载,并在流式传输时对其进行解析,并确定何时分割每个元素,这样您只需在文本块上将元素作为 JSON 处理,而不是处理所有文本。
例如,对于一个堆栈,您可能会开始添加大括号,但是一旦达到 0 级堆栈,您肯定会拥有一个元素的流并解析其中的文本。
| 归档时间: |
|
| 查看次数: |
1632 次 |
| 最近记录: |