Как избежать нехватки памяти на графике для приложения Android? - PullRequest
3 голосов
/ 10 мая 2010

Я работал над приложением для Android в Eclipse, и до сих пор моя программа не достигла сверхмалых размеров. Однако я уже столкнулся с проблемой с ошибкой нехватки памяти. Видите ли, в этой программе я использовал графику, состоящую исключительно из растровых изображений и PNG, и недавно, когда я попытался добавить в программу немного больше функциональности (в основном, включая еще несколько растровых изображений и создание дополнительного спрайта ), он начал падать в конструкторе графического потока -> конструкторе спрайта. Когда я разобрался с проблемой, это оказалось нехваткой памяти, которая, по-видимому, вызвана добавлением в программу слишком большого числа графических файлов и созданием из них Drawables.

Это было бы проблемой, поскольку у меня на самом деле не так много графических ресурсов, работающих в этой программе ... может быть, 20 или около того. Я даже еще не начал включать звук. Эти изображения не так уж и красивы. У меня такие вопросы:

1) Действительно ли программы для телефона Android ограничены объемом памяти, который они могут использовать, или это может быть что-то иное, чем 20-30 изображений ресурсов, вызывающих эту ошибку?

2) Если память для приложений Android настолько ужасна, что она не может даже обрабатывать 20-30 ресурсов изображений, загружаемых в Drawables, которые существуют одновременно, то как в мире вы должны делать достойную графику и звук? за эту вещь?

Спасибо.

Ответы [ 5 ]

3 голосов
/ 10 мая 2010

Как уже упоминали Стив и Пол, решающим фактором является то, насколько велики ваши изображения. Приложения Android ограничены 16 МБ на стандартных телефонах и 24 МБ на телефонах Hidef. Это жесткий предел. Это сильно ограничивает количество графики, которое у вас есть.

Размер графического элемента легко рассчитать: ширина х высота х размер пикселя (16 или 32 бита).

Несколько советов:

  • Вам необходимо тщательно проверить код на предмет утечек памяти. Утечка памяти в Android чрезвычайно проста, и если вы несколько раз потеряете пару битмапов, у вас быстро кончится память. Эта статья может помочь.
  • Всегда загружайте графику, используя ARGB_4444 (16 бит), если это вообще возможно. Уже одно это может сократить потребление памяти для графики в 2 раза.
  • Всегда обнуляйте и переустанавливайте ресурсы, если можете, чтобы помочь gc.
  • Постарайтесь убедиться, что графика используется только один раз. Наличие класса обработки ресурсов, который занимается этим, может быть очень полезным (по крайней мере, если вы играете в игры).
2 голосов
/ 10 сентября 2013

Самый простой способ - добавить эти 2 строки в манифест в тег приложения

андроид: hardwareAccelerated = "ложь" android: largeHeap = "true"

Но это не рекомендуется, если вы создаете приложение с эффективным использованием памяти, но это действительно работает.

1 голос
/ 10 мая 2010

Размер загружаемой графики: очень важно. Вы можете легко загрузить несколько десятков растровых изображений, если они маленькие (например, 50x50), но вы не можете сделать больше, чем несколько, если каждое из них достаточно велико, чтобы заполнить экран. Это также зависит от того, что вы пытаетесь сделать с этими изображениями. Например, если вы пытаетесь плавно повернуть изображение на 90 градусов, даже около 300x300 пикселей достаточно, чтобы почти убить приложение.

Есть несколько вещей, которые вам нужно сделать.

  1. Старайтесь не загружать изображения, пока они вам не понадобятся.
  2. Постарайтесь уменьшить их детализацию графики, если можете. Например, вы можете декодировать растровые изображения в RGB 565, ARGB_4444 или ARGB_8888, каждый из которых занимает разное количество памяти. Установите это, используя объект BitmapFactory.Options в качестве параметра при декодировании изображений.
  3. Посмотрите, можете ли вы «обмануть» - например, в памяти проще взять одно маленькое изображение и заполнить экран многократно повторяющимся изображением (например, плиткой), чем использовать одно большое изображение. Также проще обработать изображение, которое в четыре раза больше требуемого размера, но нарисованное с 2-кратным масштабным коэффициентом.
  4. Прочтите эту статью от разработчика Light Racer и его продолжений , чтобы получить представление о том, как настроить производительность - одна из самых трудных, но важных вещей, которую нужно делать при разработке. игра.
1 голос
/ 10 мая 2010

Хм .... Я написал приложения для Android с несколькими статическими изображениями (а именно для покадровой анимации), поэтому чтение вашего вопроса вызвало несколько вопросов:

  • Какую среду запуска вы используете? Это с помощью эмулятора SDK, или вы работаете на реальном телефоне? Если вы работаете в эмуляторе, возможно, вы захотите убедиться, что он был создан со спецификациями, соответствующими телефону (даже в этом случае он, вероятно, будет работать медленнее, чем на телефоне из-за специального оборудования, имеющегося в телефоне).

  • Нужно ли загружать все Drawables одновременно? Например, если вы рисуете изображение снова и снова, вы создаете Drawable для каждого его рисования, или вы можете повторно использовать один и тот же Drawable и просто изменить размер экземпляра Rect для фактического вызова?

  • Точно так же вы можете загрузить их по требованию? Например. если у вас есть приложение для создания фотоальбома, можете ли вы отображать только фотографии 1–9 и загружать фотографии 10–19 после того, как пользователь нажимает кнопку «Далее»?

  • Ваши изображения большие? Высокая плотность?

Я понимаю, что это высокоуровневый и сложный для применения; Я не думаю, что у меня есть отличное представление о том, где ваша проблема может быть из описания. Я сам набрал несколько очков snafus и смог получить максимальную экономию, внимательно посмотрев на то, как часто мне действительно нужно было использовать это ключевое слово new, и что было важно отображать и что не было. Я также нашел страницу по оптимизации для производительности очень полезной (в основном я делаю игры, некоторые примеры здесь ).

Удачи!

0 голосов
/ 11 мая 2010

Утечки памяти и создание Drawables без какой-либо причины не являются проблемой, за исключением того, что я упомяну через секунду.Однако другие вещи, о которых вы упомянули, представляют собой ценную информацию.Это видеоигра, которую я пытался создать, и поэтому, насколько я могу заметить, непрактично постоянно создавать и удалять Drawables в зависимости от того, отображаются ли они на экране прямо в эту секунду;Что касается спрайтов, я считаю, что мне нужно держать содержимое загруженным до тех пор, пока сами эти спрайты не будут удалены, а не просто исчезнут с экрана.Что касается ошибки, я, по сути, просто загрузил слишком много Drawables в память во время запуска программы, очевидно.

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

Мне придется изучить точный метод сокращения графики до 16-битной и тому подобное, потому что большая часть этого приложения на самом деле не нуждается в причудливых вещах.Я думаю, что я буду следить за этой веткой еще пару дней, на случай, если у кого-нибудь появятся другие идеи, и затем я отмечу, что на нее ответили.Спасибо, ребята.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...