Очень большой ответ SOAP – ошибка при выходе из памяти Android

У меня есть приложение, где мне нужно загрузить большой объем данных через SOAP-вызов веб-сервису в приложение, когда он будет запущен. Затем ответ отправляется в функцию, которая преобразует XML и сохраняет данные в файле db.

Эти данные имеют размер более 16 МБ, и каждый раз у меня есть java.lang.OutOfMemoryError.

Изменение веб-службы для выдачи меньших объемов данных не является вариантом.

Есть ли способ загрузить большие данные? Возможно, что-то вроде InputStream?

Это мой код

public Protocol[] getProtocols() { String METHOD_NAME = "GetProtocols"; String SOAP_ACTION = "urn:protocolpedia#GetProtocols"; Log.d("service", "getProtocols"); SoapObject response = invokeMethod(METHOD_NAME, SOAP_ACTION); return retrieveProtocolsFromSoap(response); } private SoapObject invokeMethod(String methodName, String soapAction) { Log.d(TAG, "invokeMethod"); SoapObject request = GetSoapObject(methodName); SoapSerializationEnvelope envelope = getEnvelope(request); return makeCall(envelope, methodName, soapAction); } 

Может ли кто-нибудь предложить, что делать в этом случае?

Спасибо и приветствую Мукуль

Две страtagsи, которые помогут вам решить эту проблему:

  1. Сохраните XML-stream SOAP прямо на диск при его загрузке. Не храните его в памяти.
  2. Разберите его с помощью синтаксического анализатора SAX, где вы не загружаете всю DOM в память, а скорее разбираете ее в кусках.

В зависимости от вида XML, который вы обрабатываете, использование синтаксических анализаторов SAX обычно сложнее в коде; вам придется самому отслеживать многие вещи, и вы не сможете «прыгать» из раздела в раздел вашего дерева DOM. Но потребление памяти будет ниже.

Однако обратите внимание, что многие «высокоуровневые» сетевые коммуникационные библиотеки обычно загружают весь XML DOM в память, что может иметь место здесь. Вам, вероятно, придется самостоятельно создавать и управлять HTTP-соединением, а затем вручную анализировать результат.

Просто обновление, я обнаружил, что метод «вызова» в AndroidHttpTransport заканчивается в этой строке –

  if (debug) { ByteArrayOutputStream bos = new ByteArrayOutputStream(); byte[] buf = new byte[256]; while (true) { int rd = is.read(buf, 0, 256); if (rd == -1) break; bos.write(buf, 0, rd); } bos.flush(); buf = bos.toByteArray(); //Goes out of memory here responseDump = new String(buf); is.close(); is = new ByteArrayInputStream(buf); 

вызов toByteArray занимает много памяти, поэтому, чтобы преодолеть это, вместо того, чтобы преобразовывать ответ в массив байтов, теперь я прямо пишу его в файл XML, и это сохраняется в моем местоположении. Вот –

 if (debug) { FileOutputStream bos = new FileOutputStream("/data/data/com.mypackage.myapp/response.xml"); byte[] buf = new byte[1048576]; int current = 0; int i=0; int newCurrent = 0; while ((current = inputStream.read(buf)) != -1) { newCurrent = newCurrent + current; Log.d("current", "Current = " + current + " total = "+newCurrent+" i = "+i++); bos.write(buf, 0, current); } bos.flush(); } 

У устройства больше не хватает памяти, и у меня есть собственный метод анализа, который берет этот XML и записывает его в БД.

Исправлена!

Я загрузил / скопировал здесь java-class HttpTransportSE (после копирования некоторые ошибки кода могут возникать, но все они быстро исправляются) и добавлены в мой пакет:

 https://github.com/mosabua/ksoap2-android/blob/master/ksoap2-j2se/src/main/java/org/ksoap2/transport/HttpTransportSE.java 

удалить из моего classа Connection следующую строку:

 import org.ksoap2.transport.HttpsTransportSE; 

и заменил этот код в моем новом файле HttpTransportSE.java:

 if (debug) { ByteArrayOutputStream bos = new ByteArrayOutputStream(); byte[] buf = new byte[256]; while (true) { int rd = is.read(buf, 0, 256); if (rd == -1) break; bos.write(buf, 0, rd); } bos.flush(); buf = bos.toByteArray(); //Goes out of memory here responseDump = new String(buf); is.close(); is = new ByteArrayInputStream(buf); } 

с этим

 if (debug) { FileOutputStream bos = new FileOutputStream(file); byte[] buf = new byte[256]; while (true) { int rd = is.read(buf, 0, 256); if (rd == -1) { break; } bos.write(buf, 0, rd); } bos.flush(); } 

где «файл» – это простой файловый объект, например новый файл («/ sdcard /», «myFile.xml»)

  • Как импортировать собственную библиотеку (.so-файл) в Eclipse?
  • IllegalBlockSizeException при попытке шифрования и расшифровки строки с помощью AES
  • Данные метаданных об ошибках Google Play Services v13 в AndroidManifest
  • targetSdkVersion
  • как вы отображаете карту (Google) в приложении для Android-телефонии
  • Уведомление GCM push работает после приложения Force Stop?
  • Как реализовать обработку файлов cookie на Android с помощью OkHttp?
  • Почему мы иногда вызываем супер в Android?
  • NoClassDefFoundError: android.support.v7.internal.view.menu.MenuBuilder
  • Иконка уведомления с новой системой обмена облаками Firebase
  • Что именно влияет на URLConnection.setDoOutput ()?
  • Давайте будем гением компьютера.