У меня есть представление списка с парой кнопок изображений в каждой строке. Когда вы щелкаете по строке списка, запускается новое действие. Мне пришлось создавать свои собственные вкладки из-за проблемы с макетом камеры. Действие, которое запускается для результата, является картой. Если я нажму на кнопку, чтобы запустить предварительный просмотр изображения (загрузить изображение с SD-карты), приложение вернется из действия обратно в listview
действие в обработчик результатов, чтобы повторно запустить мое новое действие, которое является не более чем виджетом изображения.
Предварительный просмотр изображения в виде списка выполняется с помощью курсора и ListAdapter
. Это делает это довольно просто, но я не уверен, как я могу поместить изображение с измененным размером (т.е. меньший размер бит, а не пиксель, как src
для кнопки изображения на лету. Поэтому я просто изменил размер изображения, полученного с камеры телефона.
Проблема в том, что я получаю ошибку «Недостаточно памяти» при попытке вернуться и перезапустить 2-е действие.
- Есть ли способ, которым я могу легко построить список адаптер за строкой, где я могу изменить размер на лету ( немного мудрее )?
Это было бы предпочтительным, поскольку мне также необходимо внести некоторые изменения в свойства виджетов / элементов в каждой строке, поскольку я не могу выбрать строку с сенсорным экраном из-за проблемы с фокусировкой. ( Я могу использовать роллер мяч. )
- Я знаю, что могу изменить размеры и сохранить внешнее изображение, но это не совсем то, что я хочу сделать, но некоторый пример кода для этого был бы неплох.
Как только я отключил изображение в списке, оно снова заработало.
К вашему сведению: вот как я это делал:
String[] from = new String[] { DBHelper.KEY_BUSINESSNAME,DBHelper.KEY_ADDRESS,DBHelper.KEY_CITY,DBHelper.KEY_GPSLONG,DBHelper.KEY_GPSLAT,DBHelper.KEY_IMAGEFILENAME + ""};
int[] to = new int[] {R.id.businessname,R.id.address,R.id.city,R.id.gpslong,R.id.gpslat,R.id.imagefilename };
notes = new SimpleCursorAdapter(this, R.layout.notes_row, c, from, to);
setListAdapter(notes);
Где R.id.imagefilename
находитсяButtonImage
.
Вот мой LogCat:
01-25 05:05:49.877: ERROR/dalvikvm-heap(3896): 6291456-byte external allocation too large for this process.
01-25 05:05:49.877: ERROR/(3896): VM wont let us allocate 6291456 bytes
01-25 05:05:49.877: ERROR/AndroidRuntime(3896): Uncaught handler: thread main exiting due to uncaught exception
01-25 05:05:49.917: ERROR/AndroidRuntime(3896): java.lang.OutOfMemoryError: bitmap size exceeds VM budget
01-25 05:05:49.917: ERROR/AndroidRuntime(3896): at android.graphics.BitmapFactory.nativeDecodeStream(Native Method)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896): at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:304)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896): at android.graphics.BitmapFactory.decodeFile(BitmapFactory.java:149)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896): at android.graphics.BitmapFactory.decodeFile(BitmapFactory.java:174)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896): at android.graphics.drawable.Drawable.createFromPath(Drawable.java:729)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896): at android.widget.ImageView.resolveUri(ImageView.java:484)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896): at android.widget.ImageView.setImageURI(ImageView.java:281)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896): at android.widget.SimpleCursorAdapter.setViewImage(SimpleCursorAdapter.java:183)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896): at android.widget.SimpleCursorAdapter.bindView(SimpleCursorAdapter.java:129)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896): at android.widget.CursorAdapter.getView(CursorAdapter.java:150)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896): at android.widget.AbsListView.obtainView(AbsListView.java:1057)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896): at android.widget.ListView.makeAndAddView(ListView.java:1616)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896): at android.widget.ListView.fillSpecific(ListView.java:1177)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896): at android.widget.ListView.layoutChildren(ListView.java:1454)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896): at android.widget.AbsListView.onLayout(AbsListView.java:937)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896): at android.view.View.layout(View.java:5611)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896): at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1119)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896): at android.widget.LinearLayout.layoutHorizontal(LinearLayout.java:1108)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896): at android.widget.LinearLayout.onLayout(LinearLayout.java:922)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896): at android.view.View.layout(View.java:5611)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896): at android.widget.FrameLayout.onLayout(FrameLayout.java:294)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896): at android.view.View.layout(View.java:5611)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896): at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1119)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896): at android.widget.LinearLayout.layoutVertical(LinearLayout.java:999)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896): at android.widget.LinearLayout.onLayout(LinearLayout.java:920)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896): at android.view.View.layout(View.java:5611)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896): at android.widget.FrameLayout.onLayout(FrameLayout.java:294)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896): at android.view.View.layout(View.java:5611)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896): at android.view.ViewRoot.performTraversals(ViewRoot.java:771)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896): at android.view.ViewRoot.handleMessage(ViewRoot.java:1103)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896): at android.os.Handler.dispatchMessage(Handler.java:88)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896): at android.os.Looper.loop(Looper.java:123)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896): at android.app.ActivityThread.main(ActivityThread.java:3742)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896): at java.lang.reflect.Method.invokeNative(Native Method)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896): at java.lang.reflect.Method.invoke(Method.java:515)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:739)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:497)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896): at dalvik.system.NativeStart.main(Native Method)
01-25 05:10:01.127: ERROR/AndroidRuntime(3943): ERROR: thread attach failed
У меня также есть новая ошибка при отображении изображения:
01-25 22:13:18.594: DEBUG/skia(4204): xxxxxxxxxxx jpeg error 20 Improper call to JPEG library in state %d
01-25 22:13:18.604: INFO/System.out(4204): resolveUri failed on bad bitmap uri:
01-25 22:13:18.694: ERROR/dalvikvm-heap(4204): 6291456-byte external allocation too large for this process.
01-25 22:13:18.694: ERROR/(4204): VM won't let us allocate 6291456 bytes
01-25 22:13:18.694: DEBUG/skia(4204): xxxxxxxxxxxxxxxxxxxx allocPixelRef failed
источник
Ответы:
Android обучение класс, « Отображение растровых изображений эффективны », предлагает некоторую большую информацию для понимания и решения , за исключением
java.lang.OutOfMemoryError: bitmap size exceeds VM budget
при загрузке Bitmaps.Читать растровые размеры и тип
BitmapFactory
Класс предоставляет несколько методов декодирования (decodeByteArray()
,decodeFile()
,decodeResource()
и т.д.) для созданияBitmap
из различных источников. Выберите наиболее подходящий метод декодирования в зависимости от источника данных вашего изображения. Эти методы пытаются выделить память для созданного растрового изображения и поэтому могут легко привести кOutOfMemory
исключению. Каждый тип метода декодирования имеет дополнительные подписи, которые позволяют вам указать опции декодирования черезBitmapFactory.Options
класс. УстановкаinJustDecodeBounds
свойства воtrue
время декодирования позволяет избежать выделения памяти, возвращаяnull
объект растрового изображения, кроме установкиoutWidth
,outHeight
иoutMimeType
. Этот метод позволяет считывать размеры и тип данных изображения до создания (и выделения памяти) растрового изображения.Чтобы избежать
java.lang.OutOfMemory
исключений, проверьте размеры растрового изображения перед его декодированием, если только вы не доверяете источнику, предоставляя вам данные изображения предсказуемого размера, которые удобно помещаются в доступную память.Загрузить уменьшенную версию в память
Теперь, когда размеры изображения известны, их можно использовать, чтобы решить, следует ли загружать полное изображение в память или вместо этого следует загружать версию с субдискретизацией. Вот некоторые факторы, которые следует учитывать:
Например, не стоит загружать изображение 1024x768 пикселей в память, если оно в конечном итоге будет отображаться в виде миниатюры 128x96 пикселей в
ImageView
.Для того, чтобы сказать , декодер субсемплировать изображение, загружая уменьшенную версию в память, набор
inSampleSize
дляtrue
вашегоBitmapFactory.Options
объекта. Например, изображение с разрешением 2048x1536, которое декодируется сinSampleSize
4, создает растровое изображение приблизительно 512x384. Загрузка этого в память использует 0,75 МБ, а не 12 МБ для полного изображения (при условии конфигурации растрового изображенияARGB_8888
). Вот метод для вычисления значения размера выборки, которое является степенью двойки, на основе целевой ширины и высоты:Чтобы использовать этот метод, сначала
inJustDecodeBounds
выполните декодирование с установленным значениемtrue
, пропустите параметры, а затем снова выполните декодирование с использованием новогоinSampleSize
значения иinJustDecodeBounds
установите наfalse
:Этот метод позволяет легко загрузить растровое изображение произвольно большого размера в файл,
ImageView
который отображает миниатюру 100x100 пикселей, как показано в следующем примере кода:Вы можете выполнить аналогичный процесс для декодирования растровых изображений из других источников, подставив соответствующий
BitmapFactory.decode*
метод по мере необходимости.источник
Чтобы исправить ошибку OutOfMemory, вы должны сделать что-то вроде этого:
Эта
inSampleSize
опция уменьшает потребление памяти.Вот полный метод. Сначала он читает размер изображения без декодирования самого содержимого. Затем он находит лучшее
inSampleSize
значение, оно должно быть степенью 2, и, наконец, изображение декодируется.источник
Я сделал небольшое улучшение в коде Федора. Он в основном делает то же самое, но без (на мой взгляд) безобразного цикла while, и это всегда приводит к степени двойки. Слава Федору за принятие оригинального решения, я застрял, пока не нашел его, а потом смог сделать это :)
источник
BitmapFactory.decodeStream()
. Не нужно ли сохранять ссылку на каждый из них, чтобы они могли быть закрыты вfinally
блоке?Я пришел из опыта iOS и был разочарован, обнаружив проблему с чем-то таким простым, как загрузка и показ изображения. В конце концов, каждый, кто имеет эту проблему, пытается отобразить изображения разумного размера. В любом случае, вот два изменения, которые исправили мою проблему (и сделали мое приложение очень отзывчивым).
1) Каждый раз, когда вы делаете
BitmapFactory.decodeXYZ()
, убедитесь, что передаетеBitmapFactory.Options
сinPurgeable
установленным наtrue
(и предпочтительно сinInputShareable
также установленным наtrue
).2) НИКОГДА не пользуйтесь
Bitmap.createBitmap(width, height, Config.ARGB_8888)
. Я имею в виду НИКОГДА! У меня никогда не было, чтобы это не вызывало ошибку памяти после нескольких проходов. Никакое количествоrecycle()
,System.gc()
независимо не помогло. Это всегда вызывало исключение. Еще один способ, который на самом деле работает, заключается в том, чтобы иметь фиктивное изображение в ваших чертежах (или другое растровое изображение, которое вы декодировали с помощью шага 1, описанного выше), измените его масштаб на любое значение, а затем манипулируйте полученным растровым изображением (например, передав его на холст). для большего удовольствия). Итак, что вы должны использовать вместо этого:Bitmap.createScaledBitmap(srcBitmap, width, height, false)
. Если по какой-либо причине вы ДОЛЖНЫ использовать метод создания грубой силы, то хотя бы проходитеConfig.ARGB_4444
.Это почти гарантированно сэкономит вам часы, если не дни. Все, что говорит о масштабировании изображения и т. Д., На самом деле не работает (если только вы не решите получить неправильный размер или ухудшенное изображение).
источник
BitmapFactory.Options options = new BitmapFactory.Options(); options.inPurgeable = true;
иBitmap.createScaledBitmap(srcBitmap, width, height, false);
решил мою проблему, которую я имел с исключением нехватки памяти на Android 4.0.0. Спасибо друг!BitmapFactory.Options.inPurgeable
иBitmapFactory.Options.inInputShareable
устарели developer.android.com/reference/android/graphics/…Это известная ошибка , это не из-за больших файлов. Поскольку Android кэширует Drawables, он исчерпывает память после использования нескольких изображений. Но я нашел для этого альтернативный способ, пропустив систему кеширования Android по умолчанию.
Решение . Переместите изображения в папку «assets» и используйте следующую функцию для получения BitmapDrawable:
источник
У меня была та же проблема, и я решил ее, избегая функций BitmapFactory.decodeStream или decodeFile, и вместо этого использовал
BitmapFactory.decodeFileDescriptor
decodeFileDescriptor
похоже, что он вызывает другие нативные методы, чем decodeStream / decodeFile.В любом случае, что сработало, так это (обратите внимание, что я добавил некоторые параметры, как некоторые имели выше, но это не то, что имело значение. Что важно, так это вызов BitmapFactory.decodeFileDescriptor вместо decodeStream или decodeFile ):
Я думаю, что есть проблема с нативной функцией, используемой в decodeStream / decodeFile. Я подтвердил, что при использовании decodeFileDescriptor вызывается другой нативный метод. Кроме того, я прочитал, что «изображения (битовые карты) распределяются не стандартным способом Java, а с помощью собственных вызовов; выделения выполняются вне виртуальной кучи, но учитываются! »
источник
Я думаю, что лучший способ избежать этого
OutOfMemoryError
- это смириться с этим и понять.Я сделал приложение, чтобы преднамеренно вызвать
OutOfMemoryError
и контролировать использование памяти.После того, как я провел много экспериментов с этим приложением, я сделал следующие выводы:
Сначала я расскажу о версиях SDK перед Honey Comb.
Растровое изображение хранится в собственной куче, но оно будет собирать мусор автоматически, вызывая recycle () не нужно.
Если {Размер кучи виртуальной машины} + {выделенная собственная память кучи}> = {Ограничение размера кучи виртуальной машины для устройства}, и вы пытаетесь создать растровое изображение, OOM будет выброшено.
УВЕДОМЛЕНИЕ: размер виртуальной машины VM считается, а не выделенная памятью.
Размер кучи виртуальной машины никогда не будет уменьшаться после увеличения, даже если выделенная память виртуальной машины уменьшается.
Таким образом, вы должны поддерживать максимальный объем памяти виртуальной машины как можно ниже, чтобы размер кучи виртуальных машин не становился слишком большим для сохранения доступной памяти для растровых изображений.
Вручную вызывать System.gc () бессмысленно, система сначала вызовет его, прежде чем пытаться увеличить размер кучи.
Собственный размер кучи тоже никогда не сократится, но это не считается OOM, так что об этом не нужно беспокоиться.
Тогда давайте поговорим о SDK Starts от Honey Comb.
Растровое изображение хранится в куче виртуальных машин, собственная память не учитывается для OOM.
Условие для OOM намного проще: {размер кучи виртуальной машины}> = {ограничение размера кучи виртуальной машины для устройства}.
Таким образом, у вас есть больше доступной памяти для создания растрового изображения с тем же пределом размера кучи, OOM с меньшей вероятностью будет выброшен.
Вот некоторые из моих наблюдений о сборке мусора и утечке памяти.
Вы можете увидеть это сами в приложении. Если Activity выполнил AsyncTask, которая все еще работала после того, как Activity была уничтожена, Activity не будет собирать мусор до завершения AsyncTask.
Это потому, что AsyncTask является экземпляром анонимного внутреннего класса, он содержит ссылку на Activity.
Вызов AsyncTask.cancel (true) не остановит выполнение, если задача заблокирована в операции ввода-вывода в фоновом потоке.
Обратные вызовы также являются анонимными внутренними классами, поэтому, если статический экземпляр в вашем проекте удерживает их и не освобождает их, память будет просачиваться.
Если вы запланировали повторяющуюся или отложенную задачу, например, Timer, и не вызывали cancel () и purge () в onPause (), память просочилась.
источник
private static class
в том же классе. Они не будут иметь никаких упоминаний об Деятельности (если вы не дадите им одно из них, конечно)В последнее время я видел много вопросов об исключениях OOM и кэшировании. В руководстве разработчика есть действительно хорошая статья по этому вопросу, но некоторые из них не могут быть реализованы соответствующим образом.
Из-за этого я написал пример приложения, которое демонстрирует кеширование в среде Android. Эта реализация еще не получила OOM.
Посмотрите на конец этого ответа для ссылки на исходный код.
Требования:
Особенности:
ListView
сторону, он просто не будет загружать растровые изображения междуЭто не включает в себя:
Образец кода:
Загружаемые изображения - это изображения (75x75) с Flickr. Однако поместите любые URL-адреса изображений, которые вы хотите обработать, и приложение уменьшит их, если они превысят максимум. В этом приложении URL-адреса просто в
String
массиве.LruCache
Имеет хороший способ иметь дело с растровыми изображениями. Тем не менее, в этом приложении я поместил экземплярLruCache
внутри другого кеш-класса, который я создал, чтобы сделать приложение более выполнимым.Критические вещи Cache.java (
loadBitmap()
метод является наиболее важным):Вам не нужно ничего редактировать в файле Cache.java, если вы не хотите реализовать кэширование на диске.
Критический материал MainActivity.java:
getView()
очень часто звонят. Обычно не стоит загружать изображения туда, если мы не реализовали проверку, которая гарантирует, что мы не будем запускать бесконечное количество потоков в строке. Cache.java проверяет, есть лиrowObject.mBitmapUrl
уже в задаче, и если это так, он не запускает другую. Поэтому мы, скорее всего, не превышаем ограничение рабочей очереди изAsyncTask
пула.Скачать:
Вы можете скачать исходный код с https://www.dropbox.com/s/pvr9zyl811tfeem/ListViewImageCache.zip .
Последние слова:
Я проверил это в течение нескольких недель, я еще не получил ни одного исключения OOM. Я проверил это на эмуляторе, на своем Nexus One и на Nexus S. Я протестировал URL-адреса изображений, которые содержат изображения в качестве HD. Единственным узким местом является то, что загрузка занимает больше времени.
Есть только один возможный сценарий, когда я могу представить себе, что OOM появится, и это если мы загрузим много действительно больших изображений и, прежде чем они будут масштабированы и помещены в кэш, будут одновременно занимать больше памяти и вызывать OOM. Но в любом случае это даже не идеальная ситуация, и, скорее всего, ее невозможно будет решить более приемлемым способом.
Сообщить об ошибках в комментариях! :-)
источник
Я сделал следующее, чтобы взять изображение и изменить его размер на лету. Надеюсь это поможет
источник
Кажется, что это очень длительная проблема, с множеством разных объяснений. Я воспользовался советом двух наиболее распространенных представленных здесь ответов, но ни один из них не решил мои проблемы с виртуальной машиной, утверждая, что она не может позволить байтам выполнить часть процесса декодирования . После некоторого копания я узнал, что настоящая проблема здесь - процесс декодирования, убирающий из кучи NATIVE .
Смотрите здесь: BitmapFactory OOM сводит меня с ума
Это привело меня к другой ветке обсуждения, где я нашел еще пару решений этой проблемы. Один из них - звонить
System.gc();
вручную после отображения вашего изображения. Но это на самом деле заставляет ваше приложение использовать БОЛЬШЕ памяти, чтобы уменьшить собственную кучу. Наилучшим решением с версии 2.0 (Donut) является использование опции BitmapFactory «inPurgeable». Так что я просто добавилo2.inPurgeable=true;
сразу послеo2.inSampleSize=scale;
.Подробнее об этом здесь: лимит кучи памяти только 6M?
Теперь, сказав все это, я тоже полный дурак с Java и Android. Так что, если вы думаете, что это ужасный способ решить эту проблему, вы, вероятно, правы. ;-) Но это творило чудеса для меня, и я нашел невозможным запустить виртуальную машину из кеш-памяти. Единственный недостаток, который я могу найти, это то, что вы уничтожаете свое кэшированное нарисованное изображение. Это означает, что если вы вернетесь назад к этому изображению, вы будете перерисовывать его каждый раз. В случае, как работает мое приложение, это не проблема. Ваш пробег может варьироваться.
источник
к сожалению, если ничего из вышеперечисленного не работает, добавьте это в свой файл манифеста . Тег внутри приложения
источник
Используйте это.
bitmap.recycle();
Это помогает без проблем с качеством изображения.источник
У меня есть гораздо более эффективное решение, которое не требует масштабирования. Просто расшифруйте ваш растровый файл только один раз, а затем кешируйте его на карте по его имени. Затем просто получите растровое изображение по имени и установите его в ImageView. Больше ничего не нужно делать.
Это будет работать, потому что фактические двоичные данные декодированного растрового изображения не сохраняются в куче виртуальной машины dalvik. Хранится снаружи. Поэтому каждый раз, когда вы декодируете растровое изображение, он выделяет память вне кучи виртуальной машины, которая никогда не возвращается GC
Чтобы лучше это оценить, представьте, что вы сохранили свое изображение в папке для рисования. Вы просто получаете изображение, выполняя getResources (). GetDrwable (R.drawable.). Это НЕ будет декодировать ваше изображение каждый раз, но будет повторно использовать уже декодированный экземпляр каждый раз, когда вы его вызываете. Так что по сути это кешируется.
Теперь, поскольку ваше изображение находится в файле где-то (или, возможно, даже поступает с внешнего сервера), вы несете ответственность за кэширование декодированного экземпляра растрового изображения для повторного использования в любом месте, где это необходимо.
Надеюсь это поможет.
источник
Я решил ту же проблему следующим образом.
источник
Здесь есть два вопроса ....
источник
Это сработало для меня!
источник
Ни один из приведенных выше ответов не помог мне, но я нашел ужасно уродливый обходной путь, который решил проблему. Я добавил очень маленькое изображение размером 1x1 пиксель в свой проект в качестве ресурса и загрузил его в свой ImageView перед вызовом в сборщик мусора. Я думаю, что, возможно, ImageView не выпускал растровое изображение, поэтому GC никогда не брал его. Это некрасиво, но пока работает.
источник
bitmap
в вышеприведенном коде есть предыдущее уже отображаемое изображение, вам нужно переработать его, очистить все ссылки на него, сделать так, чтобыimageView
оно тоже было забыто, установив крошечную заменуgc()
; и после всего этого: загрузите ваше НОВОЕ изображениеbitmap
и отобразите его...
в приведенном выше коде.Отличные ответы здесь, но я хотел полностью пригодный класс для решения этой проблемы .. поэтому я сделал один.
Вот мой класс BitmapHelper который является доказательством OutOfMemoryError :-)
источник
Это работает для меня.
и это на C # monodroid. Вы можете легко изменить путь изображения. что здесь важно, так это варианты, которые нужно установить.
источник
Похоже, что это подходящее место, чтобы поделиться своим классом утилит для загрузки и обработки изображений с сообществом, вы можете свободно его использовать и изменять.
источник
В одном из моих приложений мне нужно сделать снимок либо с
Camera/Gallery
. Если пользователь щелкает изображение с камеры (может быть 2MP, 5MP или 8MP), размер изображения варьируется отkB
s доMB
s. Если размер изображения меньше (или до 1-2 МБ) выше, код работает нормально, но если у меня есть изображение размером более 4 МБ или 5 МБ, тогдаOOM
появляется кадр :(затем я работал над решением этой проблемы и, наконец, я сделал приведенное ниже усовершенствование кода Федора (Весь кредит Федору за создание такого замечательного решения) :)
Я надеюсь, что это поможет друзьям, сталкивающимся с той же проблемой!
для более подробной информации, пожалуйста, обратитесь к этому
источник
Я только столкнулся с этой проблемой пару минут назад. Я решил это, сделав лучшую работу по управлению моим адаптером списка. Я подумал, что это проблема с сотнями изображений размером 50x50 пикселей, которые я использовал. Оказывается, я пытался раздуть свой пользовательский вид при каждом показе строки. Просто проверив, завышена ли строка, я устранил эту ошибку и использую сотни растровых изображений. Это на самом деле для Spinner, но базовый адаптер все равно работает для ListView. Это простое исправление также значительно улучшило производительность адаптера.
источник
Я потратил целый день на тестирование этих решений, и единственное, что сработало для меня, - это описанные выше подходы для получения изображения и ручного вызова GC, что, как я знаю, не обязательно, но это единственное, что сработало когда я ставлю свое приложение под нагрузочное тестирование, переключаясь между действиями. Мое приложение имеет список миниатюрных изображений в виде списка в (скажем, действие A), и когда вы нажимаете на одно из этих изображений, оно переводит вас в другое действие (например, действие B), которое показывает основное изображение для этого элемента. Когда я переключался между этими двумя действиями, я в итоге получал ошибку OOM, и приложение принудительно закрывалось.
Когда я попаду на полпути вниз по списку, произойдет сбой.
Теперь, когда я реализую следующее в упражнении B, я могу без проблем просматривать весь список и продолжать работать, продолжать и продолжать ... и это достаточно быстро.
источник
Эта проблема возникает только в эмуляторах Android. Я также столкнулся с этой проблемой в эмуляторе, но когда я зарегистрировался на устройстве, то оно работало нормально.
Поэтому, пожалуйста, проверьте устройство. Это может быть запущено в устройстве.
источник
Мои 2 цента: я решил свои ошибки OOM с помощью растровых изображений:
а) масштабирование моих изображений в 2 раза
б) использование библиотеки Пикассо в моем настраиваемом адаптере для ListView с помощью одного вызова в getView, например:
Picasso.with(context).load(R.id.myImage).into(R.id.myImageView);
источник
используйте этот код для каждого изображения, выбранного из SdCard или drewable для преобразования растрового объекта.
используйте путь к изображению в ImageData_Path.get (img_pos) .getPath () .
источник
Как правило, размер кучи устройства Android составляет всего 16 МБ (зависит от устройства / ОС, см. Размеры кучи после публикации ), если вы загружаете изображения и размер их превышает 16 МБ, из-за исключения из памяти будет выброшено исключение, вместо использования битовой карты для загрузки. изображения с SD-карты или из ресурсов или даже из сети пытаются использовать getImageUri , загрузка растрового изображения требует больше памяти, или вы можете установить для растрового изображения значение null, если ваша работа выполняется с этим растровым изображением.
источник
Все решения здесь требуют установки IMAGE_MAX_SIZE. Это ограничивает устройства более мощным аппаратным обеспечением, и если размер изображения слишком мал, на экране HD он выглядит ужасно.
Я предложил решение, которое работает с моим Samsung Galaxy S3 и несколькими другими устройствами, включая менее мощные, с лучшим качеством изображения при использовании более мощного устройства.
Суть его заключается в том, чтобы рассчитать максимальный объем памяти, выделенный для приложения на конкретном устройстве, а затем установить минимально возможный масштаб без превышения этой памяти. Вот код:
Я установил, что максимальный объем памяти, используемой этим растровым изображением, составляет 25% от максимально выделенного объема памяти. Возможно, вам придется настроить его в соответствии с вашими потребностями и убедиться, что этот растровый рисунок очищен и не остается в памяти после его использования. Обычно я использую этот код для поворота изображения (исходное и конечное растровое изображение), поэтому моему приложению необходимо одновременно загружать 2 растровых изображения в память, и 25% дают мне хороший буфер без исчерпания памяти при выполнении поворота изображения.
Надеюсь, это поможет кому-то там ..
источник
Такое
OutofMemoryException
не может быть полностью решено путем вызоваSystem.gc()
и так далее.Ссылаясь на жизненный цикл деятельностиСостояния активности определяются самой ОС с учетом использования памяти для каждого процесса и приоритета каждого процесса.
Вы можете рассмотреть размер и разрешение для каждого из используемых растровых изображений. Рекомендую уменьшить размер, изменить выборку до более низкого разрешения, обратиться к дизайну галерей (одно маленькое изображение PNG и одно оригинальное изображение).
источник
Этот код поможет загрузить большое растровое изображение из нарисованного
источник
Bitmap.Config.ARGB_565
? Если высокое качество не критично.