Как преодолеть OutOfMemoryError, когда виртуальная машина заполнена в приложении для Android?

Проверьте этот ПРОЕКТ моего приложения: Mockup


ПРОБЛЕМА:

Если я нажму кнопку ВТОРАЯ СТРАНИЦА с ПЕРВОЙ СТРАНИЦЫ, откроется новое намерение ВТОРОЙ СТРАНИЦЫ.

потом

Я нажимаю кнопку ТРЕТЬЯ СТРАНИЦА со ВТОРОЙ СТРАНИЦЫ, затем она переходит на ТРЕТЬЮ СТРАНИЦУ

потом

Я снова перехожу на ПЕРВУЮ СТРАНИЦУ, используя ПЕРВУЮ СТРАНИЦУ КНОПКИ, затем СБОЙ ПРИЛОЖЕНИЯ, выдавая ниже ошибку "Недостаточно памяти на ...."


ОШИБКА:

05-13 11:35:06.417: D/dalvikvm(11948): GC_BEFORE_OOM freed 9K, 19% free 39660K/48583K, paused 36ms, total 36ms
05-13 11:35:06.417: E/dalvikvm-heap(11948): Out of memory on a 8684816-byte allocation.
05-13 11:35:06.425: I/dalvikvm(11948): "main" prio=5 tid=1 RUNNABLE
05-13 11:35:06.425: I/dalvikvm(11948):   | group="main" sCount=0 dsCount=0 obj=0x40f01508 self=0x40d41a18
05-13 11:35:06.425: I/dalvikvm(11948):   | sysTid=11948 nice=0 sched=0/0 cgrp=apps handle=1074921264
05-13 11:35:06.425: I/dalvikvm(11948):   | schedstat=( 5318603531 1290588360 5684 ) utm=446 stm=85 core=0
05-13 11:35:06.425: I/dalvikvm(11948):   at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method)
05-13 11:35:06.425: I/dalvikvm(11948):   at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:592)
05-13 11:35:06.425: I/dalvikvm(11948):   at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:445)
05-13 11:35:06.425: I/dalvikvm(11948):   at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:781)
05-13 11:35:06.425: I/dalvikvm(11948):   at android.content.res.Resources.loadDrawable(Resources.java:1963)
05-13 11:35:06.425: I/dalvikvm(11948):   at android.content.res.TypedArray.getDrawable(TypedArray.java:601)
05-13 11:35:06.425: I/dalvikvm(11948):   at android.view.View.<init>(View.java:3443)
05-13 11:35:06.425: I/dalvikvm(11948):   at android.view.View.<init>(View.java:3376)
05-13 11:35:06.425: I/dalvikvm(11948):   at android.view.ViewGroup.<init>(ViewGroup.java:426)
05-13 11:35:06.425: I/dalvikvm(11948):   at android.widget.RelativeLayout.<init>(RelativeLayout.java:184)
05-13 11:35:06.425: I/dalvikvm(11948):   at java.lang.reflect.Constructor.constructNative(Native Method)
05-13 11:35:06.425: I/dalvikvm(11948):   at java.lang.reflect.Constructor.newInstance(Constructor.java:417)
05-13 11:35:06.433: I/dalvikvm(11948):   at android.view.LayoutInflater.createView(LayoutInflater.java:587)
05-13 11:35:06.433: I/dalvikvm(11948):   at com.android.internal.policy.impl.PhoneLayoutInflater.onCreateView(PhoneLayoutInflater.java:56)
05-13 11:35:06.433: I/dalvikvm(11948):   at android.view.LayoutInflater.onCreateView(LayoutInflater.java:660)
05-13 11:35:06.433: I/dalvikvm(11948):   at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:685)
05-13 11:35:06.433: I/dalvikvm(11948):   at android.view.LayoutInflater.rInflate(LayoutInflater.java:746)
05-13 11:35:06.433: I/dalvikvm(11948):   at android.view.LayoutInflater.rInflate(LayoutInflater.java:749)
05-13 11:35:06.433: I/dalvikvm(11948):   at android.view.LayoutInflater.rInflate(LayoutInflater.java:749)
05-13 11:35:06.433: I/dalvikvm(11948):   at android.view.LayoutInflater.inflate(LayoutInflater.java:489)
05-13 11:35:06.433: I/dalvikvm(11948):   at android.view.LayoutInflater.inflate(LayoutInflater.java:396)
05-13 11:35:06.433: I/dalvikvm(11948):   at android.view.LayoutInflater.inflate(LayoutInflater.java:352)
05-13 11:35:06.433: I/dalvikvm(11948):   at com.android.internal.policy.impl.PhoneWindow.setContentView(PhoneWindow.java:306)
05-13 11:35:06.433: I/dalvikvm(11948):   at android.app.Activity.setContentView(Activity.java:1912)
05-13 11:35:06.440: I/dalvikvm(11948):   at com.mca.LastingPowerActivity.onCreate(LastingPowerActivity.java:24)
05-13 11:35:06.440: I/dalvikvm(11948):   at android.app.Activity.performCreate(Activity.java:5163)
05-13 11:35:06.440: I/dalvikvm(11948):   at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1094)
05-13 11:35:06.440: I/dalvikvm(11948):   at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2061)
05-13 11:35:06.440: I/dalvikvm(11948):   at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2122)
05-13 11:35:06.440: I/dalvikvm(11948):   at android.app.ActivityThread.access$600(ActivityThread.java:140)
05-13 11:35:06.440: I/dalvikvm(11948):   at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1228)
05-13 11:35:06.440: I/dalvikvm(11948):   at android.os.Handler.dispatchMessage(Handler.java:99)
05-13 11:35:06.440: I/dalvikvm(11948):   at android.os.Looper.loop(Looper.java:137)
05-13 11:35:06.440: I/dalvikvm(11948):   at android.app.ActivityThread.main(ActivityThread.java:4895)
05-13 11:35:06.440: I/dalvikvm(11948):   at java.lang.reflect.Method.invokeNative(Native Method)
05-13 11:35:06.440: I/dalvikvm(11948):   at java.lang.reflect.Method.invoke(Method.java:511)
05-13 11:35:06.440: I/dalvikvm(11948):   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:994)
05-13 11:35:06.440: I/dalvikvm(11948):   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:761)
05-13 11:35:06.440: I/dalvikvm(11948):   at dalvik.system.NativeStart.main(Native Method)
05-13 11:35:06.440: D/skia(11948): --- decoder->decode returned false
05-13 11:35:06.440: D/AndroidRuntime(11948): Shutting down VM
05-13 11:35:06.440: W/dalvikvm(11948): threadid=1: thread exiting with uncaught exception (group=0x40f002a0)
05-13 11:35:06.456: E/AndroidRuntime(11948): FATAL EXCEPTION: main
05-13 11:35:06.456: E/AndroidRuntime(11948): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.mca/com.mca.LastingPowerActivity}: android.view.InflateException: Binary XML file line #18: Error inflating class <unknown>
05-13 11:35:06.456: E/AndroidRuntime(11948):    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2097)
05-13 11:35:06.456: E/AndroidRuntime(11948):    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2122)
05-13 11:35:06.456: E/AndroidRuntime(11948):    at android.app.ActivityThread.access$600(ActivityThread.java:140)
05-13 11:35:06.456: E/AndroidRuntime(11948):    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1228)
05-13 11:35:06.456: E/AndroidRuntime(11948):    at android.os.Handler.dispatchMessage(Handler.java:99)
05-13 11:35:06.456: E/AndroidRuntime(11948):    at android.os.Looper.loop(Looper.java:137)
05-13 11:35:06.456: E/AndroidRuntime(11948):    at android.app.ActivityThread.main(ActivityThread.java:4895)
05-13 11:35:06.456: E/AndroidRuntime(11948):    at java.lang.reflect.Method.invokeNative(Native Method)
05-13 11:35:06.456: E/AndroidRuntime(11948):    at java.lang.reflect.Method.invoke(Method.java:511)
05-13 11:35:06.456: E/AndroidRuntime(11948):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:994)
05-13 11:35:06.456: E/AndroidRuntime(11948):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:761)
05-13 11:35:06.456: E/AndroidRuntime(11948):    at dalvik.system.NativeStart.main(Native Method)
05-13 11:35:06.456: E/AndroidRuntime(11948): Caused by: android.view.InflateException: Binary XML file line #18: Error inflating class <unknown>
05-13 11:35:06.456: E/AndroidRuntime(11948):    at android.view.LayoutInflater.createView(LayoutInflater.java:613)
05-13 11:35:06.456: E/AndroidRuntime(11948):    at com.android.internal.policy.impl.PhoneLayoutInflater.onCreateView(PhoneLayoutInflater.java:56)
05-13 11:35:06.456: E/AndroidRuntime(11948):    at android.view.LayoutInflater.onCreateView(LayoutInflater.java:660)
05-13 11:35:06.456: E/AndroidRuntime(11948):    at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:685)
05-13 11:35:06.456: E/AndroidRuntime(11948):    at android.view.LayoutInflater.rInflate(LayoutInflater.java:746)
05-13 11:35:06.456: E/AndroidRuntime(11948):    at android.view.LayoutInflater.rInflate(LayoutInflater.java:749)
05-13 11:35:06.456: E/AndroidRuntime(11948):    at android.view.LayoutInflater.rInflate(LayoutInflater.java:749)
05-13 11:35:06.456: E/AndroidRuntime(11948):    at android.view.LayoutInflater.inflate(LayoutInflater.java:489)
05-13 11:35:06.456: E/AndroidRuntime(11948):    at android.view.LayoutInflater.inflate(LayoutInflater.java:396)
05-13 11:35:06.456: E/AndroidRuntime(11948):    at android.view.LayoutInflater.inflate(LayoutInflater.java:352)
05-13 11:35:06.456: E/AndroidRuntime(11948):    at com.android.internal.policy.impl.PhoneWindow.setContentView(PhoneWindow.java:306)
05-13 11:35:06.456: E/AndroidRuntime(11948):    at android.app.Activity.setContentView(Activity.java:1912)
05-13 11:35:06.456: E/AndroidRuntime(11948):    at com.mca.LastingPowerActivity.onCreate(LastingPowerActivity.java:24)
05-13 11:35:06.456: E/AndroidRuntime(11948):    at android.app.Activity.performCreate(Activity.java:5163)
05-13 11:35:06.456: E/AndroidRuntime(11948):    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1094)
05-13 11:35:06.456: E/AndroidRuntime(11948):    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2061)
05-13 11:35:06.456: E/AndroidRuntime(11948):    ... 11 more
05-13 11:35:06.456: E/AndroidRuntime(11948): Caused by: java.lang.reflect.InvocationTargetException
05-13 11:35:06.456: E/AndroidRuntime(11948):    at java.lang.reflect.Constructor.constructNative(Native Method)
05-13 11:35:06.456: E/AndroidRuntime(11948):    at java.lang.reflect.Constructor.newInstance(Constructor.java:417)
05-13 11:35:06.456: E/AndroidRuntime(11948):    at android.view.LayoutInflater.createView(LayoutInflater.java:587)
05-13 11:35:06.456: E/AndroidRuntime(11948):    ... 26 more
05-13 11:35:06.456: E/AndroidRuntime(11948): Caused by: java.lang.OutOfMemoryError
05-13 11:35:06.456: E/AndroidRuntime(11948):    at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method)
05-13 11:35:06.456: E/AndroidRuntime(11948):    at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:592)
05-13 11:35:06.456: E/AndroidRuntime(11948):    at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:445)
05-13 11:35:06.456: E/AndroidRuntime(11948):    at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:781)
05-13 11:35:06.456: E/AndroidRuntime(11948):    at android.content.res.Resources.loadDrawable(Resources.java:1963)
05-13 11:35:06.456: E/AndroidRuntime(11948):    at android.content.res.TypedArray.getDrawable(TypedArray.java:601)
05-13 11:35:06.456: E/AndroidRuntime(11948):    at android.view.View.<init>(View.java:3443)
05-13 11:35:06.456: E/AndroidRuntime(11948):    at android.view.View.<init>(View.java:3376)
05-13 11:35:06.456: E/AndroidRuntime(11948):    at android.view.ViewGroup.<init>(ViewGroup.java:426)
05-13 11:35:06.456: E/AndroidRuntime(11948):    at android.widget.RelativeLayout.<init>(RelativeLayout.java:184)
05-13 11:35:06.456: E/AndroidRuntime(11948):    ... 29 more

Если кто-нибудь знает, поделитесь своими ответами, чтобы я мог разрешить проблему.

Спасибо.


person Darshak    schedule 14.05.2013    source источник
comment
используйте Runtime.getRuntime().gc() для memoryoutofbound или переопределите onDestroy()..   -  person Sam    schedule 14.05.2013
comment
Установите фон для вашего макета в onResume() и отвяжите рисуемый объект от вашего макета в onPause() для каждого действия. Вы можете проверить эту ссылку для эффективной загрузки растровых изображений developer.android.com/training /отображение растровых изображений/   -  person Raghunandan    schedule 14.05.2013
comment
У вас есть версии ваших фоновых изображений во всех папках drawable-?dpi?   -  person Voicu    schedule 14.05.2013
comment
@Voicu Я использую одно высококачественное изображение для всех макетов 320dp, 360dp, 600dp и 800dp.   -  person Darshak    schedule 14.05.2013
comment
@Voicu в drawable-mdpi   -  person Darshak    schedule 14.05.2013
comment
Я считаю, что большие изображения, которые вы помещаете в drawable-mdpi, будут масштабироваться при запуске приложения на устройстве с более высокой плотностью (hdpi, xhdpi, xxhdpi), следовательно, возможность OutOfMemoryError.   -  person Voicu    schedule 14.05.2013
comment
@Voicu, но я даю им фиксированную высоту/ширину для всех различных макетов, а также даю экраны поддержки, как показано ниже ... ‹экраны поддержки android:anyDensity=false android:largeScreens=true android:normalScreens=true android:resizeable= false android:smallScreens=true /›   -  person Darshak    schedule 14.05.2013
comment
android:resizeable="false" устарел, поэтому я бы на это не рассчитывал. Что касается фиксированной высоты/ширины, я не знаю, когда масштабирование выполняется системой, поэтому не могу ответить на этот вопрос.   -  person Voicu    schedule 14.05.2013
comment
Без проблем. Но это написано здесь: developer.android.com/guide/ темы/манифест/. Этот атрибут устарел. Он был введен, чтобы помочь приложениям перейти с Android 1.5 на 1.6, когда впервые появилась поддержка нескольких экранов. Вы не должны использовать его.   -  person Voicu    schedule 14.05.2013
comment
@Darshak: можете ли вы показать мне код, как вы отображаете изображение?   -  person MAC    schedule 17.05.2013


Ответы (5)


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

person mobidev7    schedule 14.05.2013

Я также сталкиваюсь с той же проблемой, и я делаю следующее.

Когда ваша активность выходит из своего состояния и переходит к другой активности, она вызывает "onStop()" после успешного запуска activity2. Так сделай это

@Override
protected void onStop() 
{
    relativeLayout.setBackgroundDrawable(null);
}

Когда вы закроете свою деятельность2 и вернетесь к деятельности1, вызовет "onResume(). Итак, сделайте следующее:

@Override
protected void onResume() 
{
    relativeLayout.setBackgroundResource(R.drawable.home_bg);
}

Это решит вашу проблему.

person Chintan Rathod    schedule 14.05.2013
comment
Хорошо, я думаю, что этот код решит мою проблему, я попробую. Спасибо. - person Darshak; 14.05.2013
comment
сделать одну вещь. измените размер изображения, чтобы оно соответствовало размеру экрана, прежде чем применять его к фону. Средний размер выборки. - person Chintan Rathod; 15.05.2013
comment
Я уже сделал это, но я должен также создать размер планшета ... означает макеты layout-sw600dp и layout-sw800dp. в layout-sw800dp он принимает полное разрешение 800px*‹любой высоты›, в этом случае он превышает размер виртуальной машины. - person Darshak; 15.05.2013

Сначала я хотел бы упомянуть два решения, если вы используете не очень тяжелые изображения, добавьте android:largeHeap="true" в свой AndroidManifest.xml.

или

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

Вероятно, было бы лучше, если бы вы просмотрели существующие ответы на вопросы и посмотрели, совпадают ли ваши ответы с некоторыми из существующих, а если нет, напишите, что отличает вашу ситуацию.

Странная проблема нехватки памяти при загрузка изображения в объект Bitmap

Исключение нехватки памяти из-за большого размера растрового изображения

Android обрабатывает исключение нехватки памяти при обработке изображений

person user1621629    schedule 14.05.2013
comment
Сначала я хочу поблагодарить вас, но я не использую растровый объект. Просто поместите фон в макет. - person Darshak; 14.05.2013
comment
Но вы можете установить изображение в качестве фона этого макета, используя ImageView.setImageBitmap(bitmap);, попробуйте и дайте мне знать. - person user1621629; 14.05.2013

чтобы размер кучи был минимальным;

когда вы вернетесь с 3-й страницы, вы можете использовать код ниже, который очистит действия.

Intent intent = new Intent(getActivity(), MainActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);//to clear previous activities                      
startActivity(intent);

или вы можете использовать для очистки активности.

finish(); 

или вы можете просто передать контекст вместо создания нового

Activity a = (Activity) getContext();

или вы можете использовать фрагменты.

person Alp    schedule 12.05.2014

Вы должны выгрузить свои текстурные атласы и перезагрузить их, если требуется, в противном случае это определенно будет генерировать ошибку нехватки памяти.
Вот как вы можете выгрузить свою текстуру, чтобы освободить память:

    // all the textures you think are big      
    Engine.getTextureManager().unloadTexture(bg); 
    bg.clearTextureAtlasSources();    
    System.gc();

Я надеюсь, что это поможет решить вашу проблему.

person M.Mohsin    schedule 14.05.2013