Android – Кэш Bitmap занимает много памяти
Я новичок во всем предмете управления памятью, поэтому есть много вещей, которые я не понимаю.
Я пытаюсь кэшировать изображение в своем приложении, но у меня возникают проблемы с его потреблением памяти:
Весь код Chath Bitmap в значительной степени скопирован отсюда: http://developer.android.com/training/displaying-bitmaps/index.html
Я отлаживал код и проверял размер кучи в представлении DDMS в eclipse, и после этих строк кода происходит скачок в 15 мб:
- Android - ImageLoader должен быть init с настройкой перед использованием в UIL
- Программно скрыть / показать Android Soft Keyboard
- Статические ссылки очищаются - действительно ли Android разгружает classы во время выполнения, если они не используются?
- Преобразование строки в код
- В чем разница между @ + id / android: list и @ + id / list
options.inJustDecodeBounds = false; return BitmapFactory.decodeResource(res, resId, options);
в методе «decodeSampledBitmapFromResource».
Изображение – 1024×800, 75kb jpg-файл. Согласно тому, что я уже видел в Интернете, объем памяти, который предполагается использовать этому изображению, составляет около 1024 * 800 * 4 (байт на пиксель) = 3,125 МБ
Все темы, касающиеся этого предмета, не говорят, почему он занимает гораздо больше памяти, чем должен. Есть ли способ кэшировать одно изображение с разумным объемом памяти?
РЕДАКТИРОВАТЬ
Я попытался использовать метод decodeFile, предложенный в ответе @ ArshadParwez ниже. Используя этот метод, после метода BitmapFactory.decodeStream память увеличивается только на 3,5 Мб – проблема решена, но я хочу кэшировать растровые изображения непосредственно из ресурса.
Я заметил, что во время метода decodeResource есть 2 памяти «прыжки» – один из около 3,5 Мб, что разумно, а еще один странный один из 14mb. Для чего используются 14mb и почему это происходит?
- Удалить журнал вызовов в android для определенного номера
- Доступ к файлам ресурсов на Android
- Привязка данных Android с использованием тега include
- Как передать объект Bitmap из одной активности в другую
- Есть ли метод, который вычисляет факториал в Java?
- Запускайте внешнюю программу одновременно и общайтесь с ней через stdin / stdout
- Выполнение динамического кода
- Android - предотrotation перезагрузки WebView при повороте
Изображения также масштабируются в соответствии с плотностью, поэтому они могут использовать много памяти.
Например, если файл изображения находится в папке с возможностью mdpi
(которая является плотностью mdpi
), и вы запускаете ее на устройстве xhdpi
, ширина и высота будут xhdpi
. Возможно, эта ссылка может помочь вам или этому .
Таким образом, в вашем примере байты, которые будет использоваться файлом изображения, следующие:
(1024 * 2) * (800 * 2) * 4 = 13,107,200 байт.
Было бы еще хуже, если бы вы запустили его на устройстве xxhdpi
(например, HTC one и Galaxy S4).
Что ты можешь сделать? Поместите файл изображения в нужную папку плотности ( drawable-xhdpi
или drawable-xhdpi
drawable-xxhdpi
) или поместите его в drawable-nodpi
(или в папку с ресурсами) и уменьшите изображение в соответствии с вашими потребностями.
BTW вам не нужно устанавливать options.inJustDecodeBounds = false
поскольку это поведение по умолчанию. Фактически вы можете установить значение null для параметров растрового изображения.
О масштабировании вниз вы можете использовать либо путь Google, либо мой способ, каждый из которых имеет свои преимущества и недостатки.
О кешировании есть много способов сделать это. Наиболее распространенным является кеш LRU. Существует также альтернатива, которую я создал недавно (ссылка здесь или здесь ), которая позволяет вам кэшировать намного больше изображений и избегать использования OOM, но это дает вам большую ответственность.
Вы можете использовать этот метод для передачи изображения и получения растрового изображения:
public Bitmap decodeFile(File f) { Bitmap b = null; try { // Decode image size BitmapFactory.Options o = new BitmapFactory.Options(); o.inJustDecodeBounds = true; FileInputStream fis = new FileInputStream(f); BitmapFactory.decodeStream(fis, null, o); fis.close(); int IMAGE_MAX_SIZE = 1000; int scale = 1; if (o.outHeight > IMAGE_MAX_SIZE || o.outWidth > IMAGE_MAX_SIZE) { scale = (int) Math.pow( 2, (int) Math.round(Math.log(IMAGE_MAX_SIZE / (double) Math.max(o.outHeight, o.outWidth)) / Math.log(0.5))); } // Decode with inSampleSize BitmapFactory.Options o2 = new BitmapFactory.Options(); o2.inSampleSize = scale; fis = new FileInputStream(f); b = BitmapFactory.decodeStream(fis, null, o2); fis.close(); } catch (IOException e) { e.printStackTrace(); } return b; }
@Ori Wasserman: В соответствии с вашим запросом я использовал метод для получения изображений из папки ресурсов, и я тоже использовал изображение 7 МБ. Я помещал изображение 7 МБ в папку «res-> drawable» и со следующим кодом он не разбился и изображение было показано в представлении изображения:
Bitmap image = BitmapFactory.decodeResource(getResources(), R.drawable.image_7mb); loBitmap = Bitmap.createScaledBitmap(image, width_of_screen , height_of_screen, true); imageview.setImageBitmap(loBitmap);