如何获取块中的 JSON 数据以报告进度? [复制]

Posted

技术标签:

【中文标题】如何获取块中的 JSON 数据以报告进度? [复制]【英文标题】:How to get JSON data in chunks to report on progress? [duplicate] 【发布时间】:2011-10-05 18:44:12 【问题描述】:

我需要通过 REST API 下载联系人数据,我得到的是 JSON 格式。问题是,可能有很多联系人,所以我想观察进度(已经下载了多少联系人)并向用户报告(带有进度条,下面的代码在线程中运行)。

但是,似乎行 client.execute(getRequest);建立连接并一次性下载整个内容,即我的 InputStream 阅读器(以块的形式获取内容)似乎没用。现在我想知道如何让它分块工作,以便我可以报告进度?

/** prepare html get request */
HttpGet getRequest = new HttpGet(url[0]);
getRequest.addHeader("Authorization", "OAuth " + myTokens.get_access_token());

/** execute HTML request */
DefaultHttpClient client = new DefaultHttpClient();
JSONArray records = null;
HttpResponse response = client.execute(getRequest);

/** init response handlers for input stream */
InputStream input = new BufferedInputStream(response.getEntity().getContent());

byte data[] = new byte[MAX_BUFFER_SIZE];

long totalContactsCount = -1;
int readContactsCount = 0;
int currentByteReadCount = 0;

/** read response from inpus stream */
while ((currentByteReadCount = input.read(data)) != -1) 
    String readData = new String(data, 0, currentByteReadCount);
    dataString.append(readData);

    // then +1 progress on every ...,... (JSON object separator)
    if (readData.indexOf(",") >= 0) 
        readContactsCount++;
    

    // publishing the progress....
    if (totalContactsCount > 0) 
        publishProgress((int)(readContactsCount * 100 / totalContactsCount));
    

input.close();

/** transform response into JSONArray */
String result = dataString.toString();

//... convert into JSONArray

【问题讨论】:

如果你读取的缓冲区中有多个 ',' 怎么办? 你说得对——我这里简化了代码,但是会发生的情况是如果最新读取包含多个联系人,UI中的进度条不会达到100%(代码会继续读取输入流)。但是,问题仍然是下载似乎在我打开 InputStream 之前发生。 【参考方案1】:

您可以先向 Web 服务询问其拥有的联系人总数(例如 100,000),然后向其询问联系人的各个“页面”(例如 100 个联系人/页)。随着每一页的到达,您更新进度条。如果页面请求失败,只需重试该请求并继续处理。这应该是一种比尝试在一个大规模请求中获得所有 10 万联系人更可靠和有效的方法。

【讨论】:

好主意!我能够以另一种方式解决它,但这绝对是我可以在另一个应用程序中使用的概念 - 谢谢!【参考方案2】:

不幸的是,从DefaultHttpClient 的文档中可以看出,execute 方法返回的 HTTP 响应已经解析,因此已经从网络读取,因此您无法插入输入流。该流已准备好供您阅读,但正如您所注意到的,一旦它被检索到。你必须使用另一种策略。例如,尝试使用套接字 API 进行连接。

【讨论】:

谢谢。我尝试了套接字方法,但它也适用于 HttpUrlConnections(稍微简单一点)。 URL urlObject = new URL(url[0]);HttpURLConnection conn = (HttpURLConnection) urlObject.openConnection();conn.addRequestProperty("Authorization", "OAuth " + myTokens.get_access_token());InputStream input = conn.getInputStream(); 啊,完美。 HttpURLConnection 万岁! :)

以上是关于如何获取块中的 JSON 数据以报告进度? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

如何使用从 Swift 3 中的滑块中选择的 JSON 数据更新 tableviewcell?

AFHttpclient 在块中获取 json 主体但外部函数返回 null

如何以编程方式获取 FCM 发送、打开和转换的报告? [复制]

AFNetworking 2.0 从故障块中的代码 400 获取 JSON

如何使用目标 C 解析 JSON 并获取特定值? [复制]

承诺仍在 then 块中待处理 - 如何解决? [复制]