gpt4 book ai didi

检索大量数据时的Android OutOfMemoryError

转载 作者:行者123 更新时间:2023-11-29 00:19:12 30 4
gpt4 key购买 nike

我有一个应用程序可以进行网络调用并检索 XML 数据。如果没有太多数据,下面的代码可以正常工作。

public class WebClient {

private static final String TAG = WebClient.class.getSimpleName();
private String result;


private static String convertStreamToString(InputStream is) {
/*
* To convert the InputStream to String we use the
* BufferedReader.readLine() method. We iterate until the BufferedReader
* return null which means there's no more data to read. Each line will
* appended to a StringBuilder and returned as String.
*/
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
StringBuilder sb = new StringBuilder();

String line = null;
try {
while ((line = reader.readLine()) != null) {
sb.append(line + "\n");
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return sb.toString();
}


public String connect(String url) {
Log.e(TAG, "inside LoginWebClient.connect(url). url = " + url);

result = null;

HttpClient httpclient = new DefaultHttpClient();

// Prepare a request object
HttpGet httpget = new HttpGet(url);


// Execute the request
HttpResponse response;
try {
response = httpclient.execute(httpget);
// Examine the response status
Log.i(TAG, response.getStatusLine().toString());





// Get hold of the response entity
HttpEntity entity = response.getEntity();
// If the response does not enclose an entity, there is no need
// to worry about connection release

if (entity != null) {


InputStream instream = entity.getContent();
result = convertStreamToString(instream);
//Log.i(TAG, result);



// Closing the input stream will trigger connection release
instream.close();

}

} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

Log.e(TAG, "inside WebClient.connect(url). result = " + result);

return result;

}//end of connect

.

如果应用进行网络调用并返回大量数据,我会收到 OutOfMemoryError。我用谷歌搜索了这个错误,它可能是由于 StringBuilder 的内存中保存了太多数据造成的。

作为我读过的解决方法,我可以将 Stream 直接读入 String 以避免 StringBuilder。

我将 com.google.common.io.CharStreams jar 文件导入到我的项目中并尝试了以下操作:

private static String convertStreamToStringForGetAlerts(InputStream is) {

String stringFromStream = null;


try {
stringFromStream = CharStreams.toString(new InputStreamReader(is, "UTF-8"));
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return stringFromStream;
}

但我仍然收到以下错误。

06-05 09:44:40.809: E/AndroidRuntime(5851): FATAL EXCEPTION: AsyncTask #2
06-05 09:44:40.809: E/AndroidRuntime(5851): java.lang.RuntimeException: An error occured while executing doInBackground()
06-05 09:44:40.809: E/AndroidRuntime(5851): at android.os.AsyncTask$3.done(AsyncTask.java:278)
06-05 09:44:40.809: E/AndroidRuntime(5851): at java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:273)
06-05 09:44:40.809: E/AndroidRuntime(5851): at java.util.concurrent.FutureTask.setException(FutureTask.java:124)
06-05 09:44:40.809: E/AndroidRuntime(5851): at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:307)
06-05 09:44:40.809: E/AndroidRuntime(5851): at java.util.concurrent.FutureTask.run(FutureTask.java:137)
06-05 09:44:40.809: E/AndroidRuntime(5851): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076)
06-05 09:44:40.809: E/AndroidRuntime(5851): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569)
06-05 09:44:40.809: E/AndroidRuntime(5851): at java.lang.Thread.run(Thread.java:856)
06-05 09:44:40.809: E/AndroidRuntime(5851): Caused by: java.lang.OutOfMemoryError
06-05 09:44:40.809: E/AndroidRuntime(5851): at java.lang.AbstractStringBuilder.enlargeBuffer(AbstractStringBuilder.java:94)
06-05 09:44:40.809: E/AndroidRuntime(5851): at java.lang.AbstractStringBuilder.append0(AbstractStringBuilder.java:162)
06-05 09:44:40.809: E/AndroidRuntime(5851): at java.lang.StringBuilder.append(StringBuilder.java:311)
06-05 09:44:40.809: E/AndroidRuntime(5851): at java.lang.StringBuilder.append(StringBuilder.java:44)
06-05 09:44:40.809: E/AndroidRuntime(5851): at com.google.common.io.CharStreams.copy(CharStreams.java:204)
06-05 09:44:40.809: E/AndroidRuntime(5851): at com.google.common.io.CharStreams.toStringBuilder(CharStreams.java:245)
06-05 09:44:40.809: E/AndroidRuntime(5851): at com.google.common.io.CharStreams.toString(CharStreams.java:219)
06-05 09:44:40.809: E/AndroidRuntime(5851): at com.carefreegroup.rr3.carefreeoncall.WebClient.convertStreamToStringForGetAlerts(WebClient.java:151)
06-05 09:44:40.809: E/AndroidRuntime(5851): at com.carefreegroup.rr3.carefreeoncall.WebClient.connectForGetAlerts(WebClient.java:198)
06-05 09:44:40.809: E/AndroidRuntime(5851): at com.carefreegroup.rr3.carefreeoncall.WebService.getAlerts(WebService.java:1778)
06-05 09:44:40.809: E/AndroidRuntime(5851): at com.carefreegroup.rr3.carefreeoncall.ShowAlertsActivity$AsyncGetAlerts.doInBackground(ShowAlertsActivity.java:88)
06-05 09:44:40.809: E/AndroidRuntime(5851): at com.carefreegroup.rr3.carefreeoncall.ShowAlertsActivity$AsyncGetAlerts.doInBackground(ShowAlertsActivity.java:1)
06-05 09:44:40.809: E/AndroidRuntime(5851): at android.os.AsyncTask$2.call(AsyncTask.java:264)
06-05 09:44:40.809: E/AndroidRuntime(5851): at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
06-05 09:44:40.809: E/AndroidRuntime(5851): ... 4 more

有没有人知道如何在不导致此错误的情况下将此流读入字符串?

提前致谢。

最佳答案

As a workaround i have read i can read the Stream straight into a String to avoid the StringBuilder.

这没用。在幕后,CharStreams 方法最有可能使用 StringBuilder 或等效的...并且由于它不知道构建器需要多大,因此它将使用构建器用于扩展后备阵列的“双倍大小”策略。

将数据读入内存的最有效内存方式是预分配某种缓冲区(StringBuilderbyte[]char[ ] 等)的大小足以容纳字符/字节,然后填充缓冲区。如果您需要将缓冲区内容转换为字符串,您仍然需要两倍的内存量。

但这只是避免了不可避免的缩放问题。最终,XML 将太大而无法保存在内存中。您真正需要做的是更改您的代码,不要试图将整个 XML 文档保存在内存中。您可以执行以下操作之一:

  • 将其提供给事件驱动的 XML 解析器(例如 SAX)以提取感兴趣的信息,或者
  • 一次写入一个本地文件,一个字节,一个字符,一行或一个缓冲区。

关于检索大量数据时的Android OutOfMemoryError,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24055863/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com