Reputation: 429
I am having a problem to read large data from xml web service the xml file is about 5.5Mb and the code crashes and raise out of memory error
Here is my function
private static HttpResponse executePostHttpRequest(String baseUrl,
String names[],
String values[]) throws ClientProtocolException,
IOException {
final HttpClient client = newHttpClientInstance();
HttpPost request = new HttpPost(baseUrl);
boolean haveData = (names != null) && (values != null);
// if we have data, form it into request
if (haveData) {
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(values.length);
for (int i = 0; i < values.length; i++) {
nameValuePairs.add(new BasicNameValuePair(names[i], values[i]));
}
try {
request.setEntity(new UrlEncodedFormEntity(nameValuePairs, "utf-8"));
} catch (UnsupportedEncodingException e) {
request.setEntity(new UrlEncodedFormEntity(nameValuePairs));
}
}
request.addHeader("Content-Type", "application/x-www-form-urlencoded;charset=utf-8");
// return response created by executing this request
return client.execute(request);
}
and here is my dumb
12-05 23:30:31.813: I/dalvikvm-heap(443): Forcing collection of SoftReferences for 4842758-byte allocation
12-05 23:30:31.964: D/dalvikvm(443): GC freed 0 objects / 0 bytes in 143ms
12-05 23:30:31.964: E/dalvikvm-heap(443): Out of memory on a 4842758-byte allocation.
12-05 23:30:31.964: I/dalvikvm(443): "pool-1-thread-3" prio=5 tid=35 RUNNABLE
12-05 23:30:31.977: I/dalvikvm(443): | group="main" sCount=0 dsCount=0 s=N obj=0x44f92608 self=0x3d92a0
12-05 23:30:31.977: I/dalvikvm(443): | sysTid=460 nice=0 sched=0/0 cgrp=default handle=3901200
12-05 23:30:31.984: I/dalvikvm(443): at java.lang.AbstractStringBuilder.enlargeBuffer(AbstractStringBuilder.java:~97)
12-05 23:30:31.984: I/dalvikvm(443): at java.lang.AbstractStringBuilder.append0(AbstractStringBuilder.java:155)
12-05 23:30:31.984: I/dalvikvm(443): at java.lang.StringBuilder.append(StringBuilder.java:216)
12-05 23:30:31.984: I/dalvikvm(443): at com.XXXXXXXXX.api.HttpUtils.convertStreamToString(HttpUtils.java:308)
12-05 23:30:31.993: I/dalvikvm(443): at com.XXXXXXXXX.api.HttpUtils.responseToString(HttpUtils.java:331)
12-05 23:30:31.993: I/dalvikvm(443): at com.XXXXXXXXX.api.HttpUtils.executeRequest(HttpUtils.java:208)
12-05 23:30:31.993: I/dalvikvm(443): at com.XXXXXXXXX.api.HttpUtils.access$0(HttpUtils.java:188)
12-05 23:30:31.993: I/dalvikvm(443): at com.XXXXXXXXX.api.HttpUtils$3.run(HttpUtils.java:171)
12-05 23:30:31.993: I/dalvikvm(443): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1068)
12-05 23:30:31.993: I/dalvikvm(443): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:561)
12-05 23:30:31.993: I/dalvikvm(443): at java.lang.Thread.run(Thread.java:1096)
12-05 23:30:33.024: D/HttpUtils(443): Throwable: java.lang.OutOfMemoryError
12-05 23:30:35.383: D/HttpUtils(443): Throwable: java.lang.OutOfMemoryError
Any advice?
Upvotes: 1
Views: 915
Reputation: 30825
Try reading the actual input stream directly. This will allow you to use an XMLPullParser, meaning you won't have to keep the entire XML file in memory while you're parsing it. Pull parsing works by parsing the element as soon as you get it and relying on state (like a SAX parser) to keep track of where you are. It's a need concept that lets you think of you xml file as a stream of XML tags coming in.
You'd wanna do something like the following:
URL url = new URL("http://www.android.com/");
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
try {
InputStream in = new BufferedInputStream(urlConnection.getInputStream());
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
factory.setNamespaceAware(true);
XmlPullParser parser = factory.newPullParser();
parser.setInput(new InputStreamReader(in));
XmlUtils.beginDocument(parser,"results");
int eventType = parser.getEventType();
do{
XmlUtils.nextElement(parser);
parser.next();
eventType = parser.getEventType();
if(eventType == XmlPullParser.TEXT){
Log.d("test",parser.getText());
}
//...Handle other types of events...
} while (eventType != XmlPullParser.END_DOCUMENT) ;
}
finally {
urlConnection.disconnect();
}
I cobled that example together from this tutorial and this documentation. I've haven't actually tried it to see if it works though.
Upvotes: 0
Reputation: 18348
Zip the xml, text compresses very well, I had a similar issue (JSON instead of XML), not only did it solve my issues with memory, it also made the app a million times faster.
In my specific case, the JSON string changed from 5 Mb, to 200kb.
Look in this direction: Gzip in Android
Upvotes: 2