Подтвердить что ты не робот

Что делает Bitmap # recycle() в Android Honeycomb на самом деле DO?

Я пишу очень интенсивное приложение для Android Honeycomb, и я старался recycle() unused Bitmap по возможности; действительно, это необходимо, чтобы приложение работало вообще, поскольку Bitmap постоянно циклически включаются и выходят из памяти. Тем не менее, я только что реализовал onConfigurationChanged() в Activity, и поэтому (по ряду причин) я пытаюсь поместить процедуры освобождения памяти в onStop().

В настоящее время мой метод onStop():

  • устанавливает View для отображения значения по умолчанию Drawable;
  • вызывает recycle() в Bitmap, ранее используемом этими View s;
  • ссылается на ссылки Bitmap s.

К сожалению, используя профилировщик памяти Eclipse, кажется, что это вообще не влияет на использование памяти.

Как вы можете себе представить, сделав так много усилий, чтобы освободить ресурсы на номинально собранном мусором языке, я бы надеялся на немного больше эффекта. Поэтому мой вопрос: что делает recycle()? Действительно ли это запускает сборку мусора или система будет удерживать память - даже если вы вызываете System.gc() - пока она не почувствует необходимость избавиться от чего-то?

NB Я знаю, что Bitmap на самом деле не хранится в обычной куче, но я думал, что называть recycle() было достаточно, чтобы убедиться, что они выпадали из родной кучи.

ЧАСТЬ ОТВЕТА

Я обнаружил, что если ImageView содержит Bitmap, который был переработан, данные Bitmap все еще сохраняются в памяти до тех пор, пока setImageBitmap(null) не будет вызван на ImageView. Это может быть даже в случае, если вызываются setImageResource(...) или setImageDrawable(...) (они были загружены в относительно небольшой 9-патч), однако анализ MAT показывает, что это не удаляло большой Bitmap, который содержался в частной членов ImageView). Просто вызов этой функции в onStop() отобрал около 10 МБ из кучи нашего приложения. По-видимому, это может быть не так, например, для сотовых телефонов Android.

4b9b3361

Ответ 1

Я обнаружил, что в Honeycomb далее, если ImageView содержит Bitmap, который был переработан, данные Bitmap все еще сохраняются в памяти до тех пор, пока в ImageView не будет вызываться setImageBitmap(null). Это может быть даже в случае, если вызываются setImageResource(...) или setImageDrawable(...) (в этом случае очень большое растровое изображение было заменено довольно маленьким девяти патчем, но только когда setImageBitmap(null) вызывается перед загрузкой девяти патчей, фактически сохраненная память).

Ответ 2

Как говорит Джастин, битмап-данные не выделяются в куче VM. Существует ссылка на него в куче VM (что мало), но фактические данные выделяются в Native heap базовой графической библиотекой Skia. [Обратите внимание, что это может измениться на более поздних уровнях Android, но верно для 2.1 и 2.2] Когда вы делаете recycle(), который отмечает как небольшую часть кучи VM, так и фактические данные в нативной куче как свободные и доступные для GC. Но фактическая коллекция выполняется двумя различными механизмами ГХ. Часть в куче VM собрана GC Davlik, и вы можете видеть, что это происходит через DDMS. Но данные о нативной куче собраны Skia GC, который кажется более ленивым (он работает реже?). Это означает, что даже при строгой утилизации() s можно опередить встроенную GC кучи. К счастью, существуют механизмы контроля состояния родной кучи. См. BitmapFactory OOM, управляющий меня орехами.

Ответ 3

Recycle освобождает внутреннюю память, выделенную для растрового изображения. Фактический объект Bitmap останется в куче Dalvik до следующей сборки мусора (но память, занятая этим объектом, невелика).

Насколько мне известно, действительно нет способа сбросить кучу родной. Таким образом, вы не сможете узнать, не пропали ли родные данные растрового изображения с помощью кучи кучи. Однако вы должны увидеть общий объем памяти, используемой вашим приложением. Этот question должен помочь вам найти различные способы доступа к статистике использования памяти вашего приложения.