Ошибка памяти при загрузке растровых изображений
У меня есть приложение для Android с 3 ацитивами:
A1 - старты → A2 - старты → A3 - после завершения его процесса: начинается → A1
(поэтому я не "заканчиваю" (); "приложение запускает следующие действия с" startActivity (..); "все время после пользовательского взаимодействия)
поэтому в этих трех действиях есть цикл.
В каждой операции я показываю 3-9 изображений, расположенных на SD-карте, которую я загружаю с помощью следующей функции:
try
{
Uri selectedImageURI = Uri.parse(strImagePath);
File imgFile = new File(getRealPathFromURI(selectedImageURI, c));
Bitmap myBitmap = BitmapFactory.decodeFile(imgFile.getAbsolutePath());
ivTmp.setImageBitmap(myBitmap);
}catch (Exception e)
{
return null;
}
Все это работает.
Но иногда (после нескольких циклов по моей активности) мое приложение вылетает.
Logcat сообщает мне:
01-16 13:42:15.863: DEBUG/dalvikvm(23161): GC_BEFORE_OOM freed 10K, 9% free 59019K/64400K, paused 29ms, total 30ms
01-16 13:42:15.863: ERROR/dalvikvm-heap(23161): Out of memory on a 8018704-byte allocation.
01-16 13:42:15.863: ERROR/AndroidRuntime(23161): FATAL EXCEPTION: main
java.lang.OutOfMemoryError
at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method)
at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:502)
at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:355)
at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:785)
at android.content.res.Resources.loadDrawable(Resources.java:1965)
at android.content.res.Resources.getDrawable(Resources.java:660)
at android.widget.ImageView.resolveUri(ImageView.java:616)
at android.widget.ImageView.setImageResource(ImageView.java:349)
at <MyApp>.MyActivity$6.run(MyActivity.java:143)
at android.os.Handler.handleCallback(Handler.java:725)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:5039)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
at dalvik.system.NativeStart.main(Native Method)
Кто-то может дать мне несколько советов, как справляться с авариями?
Может быть, потому, что мои действия настроены на состояние "приостановлено", а не закрывать их правильно?
Ответы
Ответ 1
для быстрого исправления вы можете добавить
android:largeHeap="true"
в вашем теге приложения манифеста
ссылка здесь:
Я столкнулся с проблемой OOM для моей таблицы в разжечь и закоулки
Heap size (large)
android:largeHeap="true"
указанная спецификация упоминается для использования более крупной кучи здесь:
изменить: использовать метод кэширования битмапов ссылка здесь
Ответ 2
У меня была аналогичная проблема при отображении изображений с высоким разрешением. Я искал и применял все растровые решения андроида, приведенные в http://developer.android.com/training/displaying-bitmaps/index.html, а также следующие метаданные кешей в ссылке. но никто из них не работает. не любое правильное решение в любом месте. Затем я понял, что проблема в том, что я не мог правильно использовать структуру выпадающих папок. Я сохранял изображения с высоким разрешением в папках mdpi и hdpi. эта причина андроида увеличивает изображения до ультра размеров. Изображение размером 100 кб вызывало увеличение памяти на 20 мб благодаря блоку/монитору памяти.
поэтому я добавил эти изображения с ультраразрешением в папку xxhdpi, затем он был FIXED неожиданно. то слайдер изображения работает безупречно
Ответ 3
Да, андроид не сразу уничтожает действия, когда они не видны пользователю, но существует ряд методов жизненного цикла, которые вызываются в зависимости от текущего состояния. Проверьте http://developer.android.com/guide/components/activities.html#Lifecycle
Вы можете попробовать завершить операции в onStop() или onDestroy(), поскольку они будут вызываться, когда активность не будет видна и когда система будет работать с низкой памятью соответственно.: -)
Ответ 4
Это связано с высоким разрешением изображения, которое вы должны масштабировать растровым изображением, используя следующий код
Bitmap myBitmap = BitmapFactory.decodeFile(imgFile.getAbsolutePath());
int h = 100; // height in pixels
int w = 100; // width in pixels
Bitmap photoBitMap = Bitmap.createScaledBitmap(myBitmap,h, w, true);
ivTmp.setImageBitmap(photoBitMap);