如何以块的形式获取 JSON 数据来报告进度?
我需要通过 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
I need to download contact data via a REST API, which I get in JSON format. Issue is, it might be many many contacts, so I want to observe the progress (how many contacts have already been downloaded) and report back to the user (with a progress bar, the code below runs in a thread).
However, it seems that the line client.execute(getRequest); establishes the connection and downloads the whole content in one go, i.e. my InputStream reader (to fetch the content in chunks) seems to be useless. Now I'm wondering how to make it work in chunks, so I can report on the progress?
/** 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
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
不幸的是,从
DefaultHttpClient
的文档中可以看出,execute
方法返回一个已解析的 HTTP 响应,因此已从网络读取,因此您无法插入输入流。该流已准备好供您阅读,但正如您所注意到的,一旦它被检索。你必须使用另一种策略。例如,尝试使用套接字 API 进行连接。Unfortunatelly, as it seems from the documentation on
DefaultHttpClient
, theexecute
method returns a HTTP response, already parsed, and hence, already read from the network, so you cannot plug in the input stream. That stream is prepared for you to be read, but once it has been retreived, as you have noticed. You'd have to use another strategy. For example, trying yourself the connection using the sockets API.您可以首先向 Web 服务询问其拥有的联系人总数(例如 100,000),然后向其询问联系人的各个“页面”(例如 100 个联系人/页面)。当每个页面到达时,您都会更新进度条。如果页面请求失败,只需重试该请求并继续处理。与尝试在一次大规模请求中获取所有 10 万个联系人相比,这应该是一种更加可靠和高效的方法。
You can first ask the web service for the total number of contacts it has (say 100,000), and then ask it for individual "pages" of contacts (say 100 contacts/page). As each page arrives, you update the progress bar. If a page request fails just retry that request and continue processing. This should be a much more reliable and efficient approach than trying to get all 100k contacts in one massive request.