Android: как работает Bitmap recycle ()?
допустим, я загрузил изображение в растровый объект, как
Bitmap myBitmap = BitmapFactory.decodeFile(myFile);
Теперь, что произойдет, если я загружу другое растровое изображение, как
myBitmap = BitmapFactory.decodeFile(myFile2);
что происходит с первой myBitmap? Получает ли он собранный мусор или мне нужно вручную собрать его перед загрузкой другого растрового изображения, например. myBitmap.recycle()?
кроме того, есть ли лучший способ загрузить большие изображения и отображать их один за другим во время переработки на пути?
5 ответов:
первое растровое изображение не GC'Ed при декодировании второго. GC сделает это позже, когда решит. Если вы хотите освободить память как можно скорее, вы должны вызвать recycle () непосредственно перед декодированием второго растрового изображения.
Если вы хотите загрузить действительно большое изображение, вы должны пересчитать его. Вот пример странная проблема с памятью при загрузке изображения в растровый объект.
вам нужно будет вызвать myBitmap.recycle() перед загрузкой следующего изображения.
в зависимости от источника вашего myFile (например, если у вас нет контроля над исходным размером), при загрузке изображения вместо простой повторной выборки некоторого произвольного числа вы должны масштабировать изображение до размера дисплея.
if (myBitmap != null) { myBitmap.recycle(); myBitmap = null; } Bitmap original = BitmapFactory.decodeFile(myFile); myBitmap = Bitmap.createScaledBitmap(original, displayWidth, displayHeight, true); if (original != myBitmap) original.recycle(); original = null;Я кэширую displayWidth & displayHeight в статике, который я инициализировал в начале моей деятельности.
Display display = getWindowManager().getDefaultDisplay(); displayWidth = display.getWidth(); displayHeight = display.getHeight();
Я думаю, что проблема заключается в следующем: на предварительных версиях Honeycomb Android фактические необработанные растровые данные хранятся не в памяти виртуальной машины, а в собственной памяти. Это родная память и освобождается, когда соответствующий java , когда у вас заканчивается собственная память, Dalvik GC не запускается, поэтому возможно, что ваше приложение использует очень мало памяти java, поэтому Dalvik GC никогда не вызывается, но он использует тонны родной память для растровых изображений, которая в конечном итоге вызывает ошибку OOM.
по крайней мере это мое предположение. К счастью, в Honeycomb и позже все растровые данные хранятся в виртуальной машине, поэтому вам не нужно использовать
recycle()на всех. Но для миллионов пользователей 2.3 (фрагментация трясет кулаком), вы должны использоватьrecycle()везде, где это возможно (а большая морока). Или в качестве альтернативы вы можете вызвать GC вместо этого.
после того, как растровое изображение было загружено в память , на самом деле он был сделан из двух частей данных. Первая часть включает некоторую информацию о растровом изображении, другая часть включает информацию о пикселях растрового изображения( оно составлено массивом байтов). Первая часть существует в используемой памяти Java, вторая часть существует в используемой памяти C++. Он может использовать память друг друга напрямую. Растровый.recycle() используется для освобождения памяти C++. Если вы только это сделаете, GC будет собирать часть java, а память C всегда используемый.
Тимммм был прав.
по данным : http://developer.android.com/training/displaying-bitmaps/cache-bitmap.html
кроме того, до Android 3.0 (уровень API 11) резервные данные растрового изображения хранились в собственной памяти, которая не была выпущена предсказуемым образом, что потенциально может привести к кратковременному превышению ограничений памяти и сбою приложения.
Comments