Intereting Posts
Отключить кнопку аппаратного возврата в приложении Ionic? Как получить растровое изображение, предоставляющее URI, java.io.FileNotFoundException: Нет поставщика контента: /sdcard/Hello/1310610722879.jpg Панель инструментов AppCompat_v7 как панель действий, не отображающая «всегда» действия из меню, но панель инструментов API Получение разницы между двумя датами Android Преобразование XML в объект JSON в Android Android: startActivityForResult & setResult для класса вида и класса активности Можно ли ссылаться на другую строку в файле strings.xml? Можно ли изменить левую выделенную кнопку в Selector xml? SQLite, как получить все имена таблиц в базе данных? Каково определение ценности, предоставляемой функцией Android View.getHitRect ()? Заполнение Spinner, которое отображает строки в числа из XML в Android Приложение несовместимо с Nexus7, работающим с Marshmallow Android, как сфокусировать ActionBar searchView Отображать изображение из URL-адресов и задач ориентации экрана BluetoothAdapter ActionDiscoveryFinished

Ошибка воли за пределами памяти, странная попытка размещения

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

java.lang.OutOfMemoryError at com.android.volley.toolbox.DiskBasedCache.streamToBytes(DiskBasedCache.java:316) at com.android.volley.toolbox.DiskBasedCache.readString(DiskBasedCache.java:526) at com.android.volley.toolbox.DiskBasedCache.readStringStringMap(DiskBasedCache.java:549) at com.android.volley.toolbox.DiskBasedCache$CacheHeader.readHeader(DiskBasedCache.java:392) at com.android.volley.toolbox.DiskBasedCache.initialize(DiskBasedCache.java:155) at com.android.volley.CacheDispatcher.run(CacheDispatcher.java:84) 

«Diskbasedbache» пытается выделить более 1 гигабайта памяти, без видимой причины

Как я могу сделать это не так? Кажется, что проблема связана с Volley, или, может быть, с кэшем на основе диска, но я не вижу (со стека трассировки), как «очистить» этот кеш или выполнить условную проверку или обработать это исключение

Проницательность оценена

Solutions Collecting From Web of "Ошибка воли за пределами памяти, странная попытка размещения"

В streamToBytes() сначала будут streamToBytes() новые байты по длине кеш-файла, ваш файл кеша будет слишком большим, чем максимальный размер кучи приложения?

 private static byte[] streamToBytes(InputStream in, int length) throws IOException { byte[] bytes = new byte[length]; ... } public synchronized Entry get(String key) { CacheHeader entry = mEntries.get(key); File file = getFileForKey(key); byte[] data = streamToBytes(..., file.length()); } 

Если вы хотите очистить кеш, вы можете сохранить ссылку на DiskBasedCache , после того, как DiskBasedCache свободное время, используйте ClearCacheRequest и передайте этот экземпляр кэша в:

 File cacheDir = new File(context.getCacheDir(), DEFAULT_CACHE_DIR); DiskBasedCache cache = new DiskBasedCache(cacheDir); RequestQueue queue = new RequestQueue(cache, network); queue.start(); // clear all volley caches. queue.add(new ClearCacheRequest(cache, null)); 

Таким образом, будут очищены все кеши, поэтому я предлагаю вам внимательно их использовать. Конечно, вы можете выполнять conditional check , просто повторяя файлы cacheDir , оценивая , что было слишком велико, а затем удалили.

 for (File cacheFile : cacheDir.listFiles()) { if (cacheFile.isFile() && cacheFile.length() > 10000000) cacheFile.delete(); } 

Volley не был дизайном как большое решение для кэширования данных, это обычный кэш запросов, не хранящий большие данные в любое время.

————- Обновление на 2014-07-17 ————-

На самом деле, очистить все кеши окончательный путь, также не разумный способ, мы должны подавить эти большой кэш использования запроса, когда мы уверены, что это будет, и если не уверены? Мы по-прежнему можем определить размер данных ответа, большой или нет, а затем вызвать setShouldCache(false) чтобы отключить его.

 public class TheRequest extends Request { @Override protected Response<String> parseNetworkResponse(NetworkResponse response) { // if response data was too large, disable caching is still time. if (response.data.length > 10000) setShouldCache(false); ... } } 

Я испытал ту же проблему.

Мы знали, что при инициализации кеша у нас не было файлов размером в ГБ. Это также произошло при чтении строк заголовков, которые никогда не должны быть длинными GB.

Таким образом, это выглядело так, что длина читалась неправильно с помощью readLong.

У нас было два приложения с примерно одинаковыми настройками, за исключением того, что у одного приложения было два независимых процесса, созданных при запуске. Основной процесс приложения и процесс SyncAdapter после шаблона адаптера синхронизации. Только приложение с двумя процессами потерпит крах. Эти два процесса будут независимо инициализировать кеш.

Однако DiskBasedCache использует одно и то же физическое местоположение для обоих процессов. В заключение мы пришли к выводу, что параллельные инициализации приводят к одновременному чтению и записи одних и тех же файлов, что приводит к плохому считыванию параметра размера.

У меня нет полного доказательства того, что это проблема, но я планирую проверить тестовое приложение.

В краткосрочной перспективе мы просто поймали слишком большое распределение байтов в streamToBytes и выбросили исключение IOException, чтобы Volley поймал исключение и просто удалил файл. Однако, вероятно, было бы лучше использовать отдельный кэш диска для каждого процесса.

  private static byte[] streamToBytes(InputStream in, int length) throws IOException { byte[] bytes; // this try-catch is a change added by us to handle a possible multi-process issue when reading cache files try { bytes = new byte[length]; } catch (OutOfMemoryError e) { throw new IOException("Couldn't allocate " + length + " bytes to stream. May have parsed the stream length incorrectly"); } int count; int pos = 0; while (pos < length && ((count = in.read(bytes, pos, length - pos)) != -1)) { pos += count; } if (pos != length) { throw new IOException("Expected " + length + " bytes, read " + pos + " bytes"); } return bytes; } 

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

К счастью, этот вопрос был зафиксирован в официальном репо ВОЛЛ:

См. Связанные проблемы в зеркале андроид-волейбола: