Предотвращение исключения OutOfMemory при выполнении больших сетевых запросов из приложения Android - PullRequest
2 голосов
/ 29 февраля 2012

Я занимаюсь разработкой приложения, и при первом запуске я ожидаю загрузки большого количества данных в формате JSON (скажем, 10-20 МБ).Все эти данные передаются в одном сетевом запросе (причина в том, что данные генерируются динамически для каждого запроса).Движущийся код выдает исключение OOM при получении данных (in builder.append()):

  public static String readToString(InputStream stream) throws IOException {
    BufferedReader in = null;
    StringBuilder builder = new StringBuilder();
    in = new BufferedReader(new InputStreamReader(stream, "UTF-8"));
    char[] buffer = new char[1024];
    int read = 0;
    while ((read = in.read(buffer, 0, 1024)) > 0) {
      builder.append(buffer, 0, read);
    }
    in.close();
    return builder.toString();
  }

Что я могу сделать, чтобы избежать этой ошибки?Я думаю о попытке сохранить данные во временный файл и затем обработать его.Но я не уверен, сработает ли это или нет.Другая возможность, по-видимому, состоит в том, чтобы разделить сетевой ввод-вывод на две части: во-первых, приложение получает данные о том, что оно должно загрузить, а во-вторых, оно фактически загружает данные.

Любой совет?

Ответы [ 2 ]

3 голосов
/ 29 февраля 2012

Следуйте первой мысли - сохраните данные во временный файл (пожалуйста, SDCard. 20 МБ во внутренней памяти слишком велико).Сначала необходимо открыть соединение для загрузки.

InputStream is = URL("your_request_string").openStream();

Затем создайте новый файл в SDCard

File f = new File(Environment.getExternalStorageDirectory(), "temp.dat");

Используя только что созданный файл, откройте OutputStream.

FileOutputStream = new FileOutputStream(f);

Теперь вы можете использовать этот код для перевода:

public static void CopyStream(InputStream is, OutputStream os) {
    final int buffer_size=8192;
    try
    {
        byte[] bytes=new byte[buffer_size];
        for(;;)
        {
          int count=is.read(bytes, 0, buffer_size);
          if(count==-1)
              break;
          os.write(bytes, 0, count);
        }
    }
    catch(Exception ex){}
}
1 голос
/ 29 февраля 2012

Начиная с API 11, http://developer.android.com/reference/android/util/JsonReader.html используется для чтения потока данных Json без выделения всей большой строки.

Для предыдущих версий существует множество сторонних библиотек JSON, которые предлагают возможность потокового чтения на основе событий.

...