0

我已经阅读了很多关于 SO 的问题,例如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但没有运气......

4

1 回答 1

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 传递给它。

希望它会有所帮助

于 2013-06-28T08:27:15.237 回答