SOAP - Очень большой XML-ответ - OutOfMemoryError - PullRequest
3 голосов
/ 03 августа 2011

Во-первых, этот вопрос выглядит следующим образом: Очень большой ответ SOAP - Android - из-за ошибки памяти тема. Из-за моей слабости в английском языке и схожести этой проблемы, чтобы облегчить понимание, некоторые фрагменты утверждений были скопированы.

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

Размер данных превышает 11 МБ, и у меня есть java.lang.OutOfMemoryError каждый раз.

Модификация веб-службы для выдачи меньших объемов данных невозможна.

Я использую «запрос Http» для получения данных. Я знаю, что: мой запрос в порядке, мыло и Wireshark возвращают ожидаемые ответы.

Но мой AVD не может пройти эту линию

HttpResponse httpResponse = httpClient.execute(httpPost);

После нескольких минут работы (в течение которых wireshark восстанавливает некоторые ожидаемые запросы) эта ошибка сделана

 Out of memory on a 16705124-byte allocation.

Я пытался обновить размер SD-карты до 20 ГБ, но ошибка все еще.

Парсинг httpResponse, вероятно, следующий шаг, возможно ли проанализировать HttpResponse, пока он получает данные, фрагментируя их на несколько частей, например?

У вас есть идея?

Спасибо, Dsandre

Ответы [ 3 ]

4 голосов
/ 08 августа 2011

Спасибо, Грэм, открытие соединения работает как поток байтов. Если кому-то это может пригодиться, это мой исходный код

        //Make a temporary file to save data
        File responseFile = File.createTempFile("SOAP", "xml", context.getFilesDir());      
        int nbCharRead = 0; int i=0; int totalRead = 0;

        //Send query
        OutputStream outputS = url_Connection.getOutputStream();
        Writer w_out = new OutputStreamWriter(outputS);
        w_out.write(webServiceXml);
        w_out.flush();
        w_out.close();


        //Buffers
        BufferedReader bufReader = new BufferedReader(new InputStreamReader(url_Connection.getInputStream()));
        BufferedWriter bufWriter = new BufferedWriter(new FileWriter(responseFile));
        char[] buffer = new char[10000];



        while((nbCharRead = bufReader.read(buffer, 0, 10000)) != -1)
        {
            totalRead += nbCharRead;
            Log.d("Test InputStream", "i: " + i++ +" - " + nbCharRead + " -> " + totalRead);
            bufWriter.write(buffer, 0, nbCharRead );
        }       

        if(bufWriter != null)
        {
            bufWriter.flush();
            bufWriter.close();
        }


        Log.w(MsgLog, "--- Stream Got--- ; Total : " + totalRead);
3 голосов
/ 03 августа 2011

Вы можете открыть соединение как поток байтов:

URL url = new URL("www.google.com");
InputStream in = new BufferedInputStream(url.openStream());
byte[] buffer = new byte[1024];
int chunk = 0;
while ((chunk =in.read(buffer ))!=-1)
{
    proccessChunk(chunk);
}
in.close();

С этого момента вы сможете измерять ответ и обрабатывать его побитно, сохраняя каждый обработанный фрагмент в текстовые файлы (или, если это реляционные данные для SQLite).

HTH

1 голос
/ 03 августа 2011

Возможно, вы загружаете весь ответ в память (возможно, в виде строки?). Устройства Android, особенно старые, работающие на старом оборудовании и старых версиях операционной системы, имеют ограниченный размер кучи vm. Я не могу вспомнить точное число, но быстрый Google показывает, что это всего лишь 16 МБ.

Лучший способ обработать ответы, которые являются большими в устройствах Android, состоит в том, чтобы прочитать это как поток. Я думаю, что последние версии apache-commons / jakarta httpclient поддерживают потоковую передачу.

...