Я был бы очень признателен, если бы кто-то мог подтвердить, что я правильно решил проблему ниже или если есть альтернативное решение?
У меня есть приложение, которое загружает большое изображение (например, 800 * 1720 пикселей) в память и отображает его в scrollview. Изображение представляет собой план этажей для музея, и мне нужна простая карта, например, опыт прокрутки и масштабирования. Изображение загрузилось отлично на более старые устройства, но вызвало ошибку из памяти на Samsung Galaxy S3.
Глядя на сообщения LogCat, выяснилось, что при создании растрового изображения 22MB выделялось для растрового изображения вместо 800 * 1720 * 4 = 5,5 МБ. По существу, в 4 раза больше памяти выделялось по требованию других устройств и нажимало использование памяти на размер кучи размером 50 МБ.
Рекомендуемое решение этой проблемы - использовать параметр BitmapFactory.Options.inSampleSize
, чтобы уменьшить разрешение загруженного изображения и потребовать меньше памяти. Однако это снижает качество изображения, и я действительно хочу отображать его на полном размере в оригинальном качестве, так как отлично работает на старых устройствах.
После большой царапины головы я пришел к выводу, что проблема заключается в том, что плотность пикселей на экранах S3 WXGA составляет 2,0 и, следовательно, для каждого пикселя на изображении, битмап фактически выделяет 4 пикселя. С небольшим количеством проб и ошибок я обнаружил, что могу предотвратить это, установив options.inScaled = false;
http://developer.android.com/reference/android/graphics/BitmapFactory.Options.html#inScaled
По пути я также понял, что могу сократить использование памяти в два раза до 2,7 МБ, используя более низкую глубину цвета 2 пикселя вместо 4 пикселей, установив options.inPreferredConfig = Bitmap.Config.RGB_565;
. Для моих напольных покрытий это не повлияло на качество видимого изображения.
Окончательный код был таким образом:
String uri = "drawable/floorplan";
int imageResource = getResources().getIdentifier(uri, null, getPackageName());
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig = Bitmap.Config.RGB_565;
options.inScaled = false;
Bitmap bm = BitmapFactory.decodeResource(getResources(), imageResource, options);
IVfloorplan.setImageBitmap(bm);
При отображении этого растрового изображения вам нужно масштабировать его. Чтобы выработать масштаб, вы можете получить плотность пикселей из:
float density = getResources().getDisplayMetrics().density;
Я уменьшил использование памяти для растрового изображения с 22 МБ до 2,7 МБ, что в куче 50 МБ значительно.