获取JSON数据并以字符串形式读取速度很慢(与我的浏览器相比)

时间:2013-06-28 07:49:03

标签: android json performance androidhttpclient

关于thisthisthisthis,我已经阅读过很多关于此问题的问题。

我的问题如下:我有一个驻留在服务器上的json数据。 Tha数据被缓存并作为gzip请求,因此整个大小约为110kb。如果您尝试使用firefox检索此数据(并使用firebug计算时间),则需要 3秒才能下载并显示。

同样的数据需要 10 - 15秒(有时甚至更多)才能下载并转换为我的Android应用上的字符串。 (请注意,我使用的是Nexus 10平板电脑,这是同类产品中处理速度最快的平板电脑之一。)

请参阅下面的代码:

List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2);

// ... nameValuePairs omitted

HttpParams params = new BasicHttpParams();
HttpConnectionParams.setConnectionTimeout(params, 3500);
HttpConnectionParams.setSoTimeout(params, 14000);
HttpConnectionParams.setTcpNoDelay(params, false);

params.setParameter(CoreProtocolPNames.PROTOCOL_VERSION, HttpVersion.HTTP_1_1);
params.setBooleanParameter(CoreProtocolPNames.USE_EXPECT_CONTINUE, true);   

HttpClient httpclient = new DefaultHttpClient(params); 
HttpPost httppost = new HttpPost(mContext.getResources().getString(R.string.newsUrl));
httppost.addHeader("Accept-Encoding", "gzip");

try { 
    // Add your data 
    httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs, "UTF-8")); 
    Log.i(TAG, "NewsFetcher, Request started at: " + (int)(System.currentTimeMillis() / 1000));

    // Execute HTTP Post Request 
    HttpResponse response = httpclient.execute(httppost);

    Log.i(TAG, "NewsFetcher, Request ended at: " + (int)(System.currentTimeMillis() / 1000));

    if (response.getStatusLine().getStatusCode() == 200 || response.getStatusLine().getStatusCode() == 204 || response.getStatusLine().getStatusCode() == 304 ) {

        Header contentEncoding = response.getFirstHeader("Content-Encoding");

        String webAppResponse; 
        if (contentEncoding != null && contentEncoding.getValue().equalsIgnoreCase("gzip")) { 
            Log.i(TAG, "NewsFetcher, InputStream(gzip) received at : " + (int)(System.currentTimeMillis() / 1000)); 
            webAppResponse = IOUtils.toString(new GZIPInputStream(response.getEntity().getContent()), "UTF-8"); 
        } else { 
            Log.i(TAG, "NewsFetcher, InputStream(plain) received at : " + (int)(System.currentTimeMillis() / 1000)); 
            webAppResponse = IOUtils.toString(response.getEntity().getContent(), "UTF-8"); 
        }

        Log.i(TAG, "NewsFetcher, InputStream ended at : " + (int)(System.currentTimeMillis() / 1000));

        // try to detect any error 
        try { 
            JSONArray webAppResultJSON = new JSONArray(webAppResponse); 
            ArrayList<NewsItem> parsedItems = parseJSON(webAppResultJSON);

            return new FetchResult(UpdateStatus.FETCH_OK, parsedItems); 
        // ... exceptions omitted
        } catch (Exception e) { 
            Log.e(TAG, "General Exception 1"); 
            e.printStackTrace(); 
            return new FetchResult(UpdateStatus.FETCH_GENERAL_ERROR, null); 
        } 
    } else {
        return new FetchResult(UpdateStatus.FETCH_HTTP_ERROR, null); 
    }
// ... exceptions omitted
} catch (Exception e) { 
    Log.e(TAG, "General Exception 2");
    e.printStackTrace(); 
    return new FetchResult(UpdateStatus.FETCH_GENERAL_ERROR, null); 
}

以下是logcat的结果

06-28 10:43:11.486: I/com.package.my.logic.NewsFetcher(3102): NewsFetcher, Request started at: 1372405391
06-28 10:43:17.986: I/com.package.my.logic.NewsFetcher(3102): NewsFetcher, Request ended at: 1372405397
06-28 10:43:17.986: I/com.package.my.logic.NewsFetcher(3102): NewsFetcher, InputStream(gzip) received at : 1372405397
06-28 10:43:30.266: I/com.package.my.logic.NewsFetcher(3102): NewsFetcher, InputStream ended at : 1372405410

如果从1372405410中减去1372405391,则 19秒!你能建议对上面的代码进行任何优化吗?

我还尝试使用HttpURLConnection代替HttpPost,但没有运气......

1 个答案:

答案 0 :(得分:0)

似乎

            webAppResponse = IOUtils.toString(new GZIPInputStream(response.getEntity().getContent()), "UTF-8"); 

占用大部分时间(13秒)。

我曾经写过这种方法,效果很好。也许它会比IOUtils更好:

public String inputStreamToString (InputStream inputStream) throws IOException {

    StringBuilder builder = new StringBuilder();

    BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));

    String line;

    while ((line = reader.readLine()) != null) {
        builder.append(line);
    }

    return builder.toString();
}

只需将GZIPInputStream传递给它。

希望它会有所帮助