Ошибка Android HttpClient Outof memory (данные xml) - PullRequest
1 голос
/ 06 декабря 2011

У меня проблема с чтением больших данных из веб-службы xml, размер файла xml составляет около 5,5 МБ, происходит сбой кода и возникает ошибка нехватки памяти

Вот моя функция

 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);

}

и вот мой тупой

        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

Любой совет?

Ответы [ 2 ]

2 голосов
/ 06 декабря 2011

Сжатие xml, текст сжимается очень хорошо, у меня была похожая проблема (JSON вместо XML), она не только решала мои проблемы с памятью, но и делала приложение в миллион раз быстрее.

В моем конкретном случае строка JSON изменилась с 5 МБ до 200 КБ.

Посмотрите в этом направлении: Gzip в Android

0 голосов
/ 06 декабря 2011

Попробуйте прочитать реальный входной поток напрямую. Это позволит вам использовать XMLPullParser , что означает, что вам не нужно будет хранить весь XML-файл в памяти, пока вы его анализируете. Синтаксический анализ Pull выполняется путем синтаксического анализа элемента, как только вы его получите, и полагается на состояние (например, анализатор SAX), чтобы отслеживать, где вы находитесь. Это необходимая концепция, которая позволяет вам думать о своем XML-файле как о поступающем потоке XML-тегов.

Вы бы хотели сделать что-то вроде следующего:

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();
} 

Я собрал этот пример вместе с этого урока и этой документацией . Я на самом деле не пробовал, чтобы увидеть, работает ли он, хотя.

...