J'utilise un fond JPG pour la vue Root de mon activité, et je le mets dans drawable
dossier. Tout allait bien jusqu'à ce que je décide d'utiliser deux fonds d'écran différents pour les orientations portrait et paysage. J'ai donc placé le deuxième fond d'écran dans drawable-land
dossier.
Le problème est le suivant : lorsque je teste l'application sur un appareil réel, chaque fois que je change deux fois d'orientation (de portrait à paysage, puis de paysage à portrait), l'application se bloque et je vois un loooooong journal d'erreurs, concernant OutOfMemoryException
:
09-08 14:13:21.567: E/dalvikvm-heap(16536): Out of memory on a 16384016-byte allocation.
09-08 14:13:21.567: I/dalvikvm(16536): "main" prio=5 tid=1 RUNNABLE
09-08 14:13:21.567: I/dalvikvm(16536): | group="main" sCount=0 dsCount=0 obj=0x40ad2478 self=0x149a9d0
09-08 14:13:21.567: I/dalvikvm(16536): | sysTid=16536 nice=0 sched=0/0 cgrp=default handle=1074488712
09-08 14:13:21.567: I/dalvikvm(16536): | schedstat=( 0 0 0 ) utm=346 stm=52 core=1
09-08 14:13:21.567: I/dalvikvm(16536): at android.graphics.Bitmap.nativeCreate(Native Method)
09-08 14:13:21.567: I/dalvikvm(16536): at android.graphics.Bitmap.createBitmap(Bitmap.java:605)
09-08 14:13:21.567: I/dalvikvm(16536): at android.graphics.Bitmap.createBitmap(Bitmap.java:551)
09-08 14:13:21.567: I/dalvikvm(16536): at android.graphics.Bitmap.createScaledBitmap(Bitmap.java:437)
09-08 14:13:21.567: I/dalvikvm(16536): at android.graphics.BitmapFactory.finishDecode(BitmapFactory.java:530)
09-08 14:13:21.567: I/dalvikvm(16536): at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:505)
09-08 14:13:21.567: I/dalvikvm(16536): at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:357)
09-08 14:13:21.567: I/dalvikvm(16536): at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:777)
09-08 14:13:21.567: I/dalvikvm(16536): at android.content.res.Resources.loadDrawable(Resources.java:1940)
09-08 14:13:21.567: I/dalvikvm(16536): at android.content.res.TypedArray.getDrawable(TypedArray.java:601)
09-08 14:13:21.567: I/dalvikvm(16536): at android.view.View.<init>(View.java:2844)
09-08 14:13:21.567: I/dalvikvm(16536): at android.view.View.<init>(View.java:2781)
09-08 14:13:21.567: I/dalvikvm(16536): at android.view.ViewGroup.<init>(ViewGroup.java:412)
09-08 14:13:21.577: I/dalvikvm(16536): at android.widget.RelativeLayout.<init>(RelativeLayout.java:179)
09-08 14:13:21.577: I/dalvikvm(16536): at java.lang.reflect.Constructor.constructNative(Native Method)
09-08 14:13:21.577: I/dalvikvm(16536): at java.lang.reflect.Constructor.newInstance(Constructor.java:417)
09-08 14:13:21.577: I/dalvikvm(16536): at android.view.LayoutInflater.createView(LayoutInflater.java:586)
09-08 14:13:21.577: I/dalvikvm(16536): at com.android.internal.policy.impl.PhoneLayoutInflater.onCreateView(PhoneLayoutInflater.java:56)
09-08 14:13:21.577: I/dalvikvm(16536): at android.view.LayoutInflater.onCreateView(LayoutInflater.java:653)
09-08 14:13:21.577: I/dalvikvm(16536): at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:678)
09-08 14:13:21.577: I/dalvikvm(16536): at android.view.LayoutInflater.inflate(LayoutInflater.java:466)
09-08 14:13:21.577: I/dalvikvm(16536): at android.view.LayoutInflater.inflate(LayoutInflater.java:396)
09-08 14:13:21.577: I/dalvikvm(16536): at android.view.LayoutInflater.inflate(LayoutInflater.java:352)
09-08 14:13:21.577: I/dalvikvm(16536): at com.android.internal.policy.impl.PhoneWindow.setContentView(PhoneWindow.java:255)
09-08 14:13:21.577: I/dalvikvm(16536): at android.app.Activity.setContentView(Activity.java:1835)
09-08 14:13:21.577: I/dalvikvm(16536): at com.test.IndexActivity.onCreate(IndexActivity.java:58)
09-08 14:13:21.577: I/dalvikvm(16536): at android.app.Activity.performCreate(Activity.java:4465)
09-08 14:13:21.577: I/dalvikvm(16536): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1049)
09-08 14:13:21.577: I/dalvikvm(16536): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1931)
09-08 14:13:21.577: I/dalvikvm(16536): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1992)
09-08 14:13:21.577: I/dalvikvm(16536): at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:3371)
09-08 14:13:21.577: I/dalvikvm(16536): at android.app.ActivityThread.access$700(ActivityThread.java:127)
09-08 14:13:21.577: I/dalvikvm(16536): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1162)
09-08 14:13:21.577: I/dalvikvm(16536): at android.os.Handler.dispatchMessage(Handler.java:99)
09-08 14:13:21.577: I/dalvikvm(16536): at android.os.Looper.loop(Looper.java:137)
09-08 14:13:21.577: I/dalvikvm(16536): at android.app.ActivityThread.main(ActivityThread.java:4441)
09-08 14:13:21.577: I/dalvikvm(16536): at java.lang.reflect.Method.invokeNative(Native Method)
09-08 14:13:21.577: I/dalvikvm(16536): at java.lang.reflect.Method.invoke(Method.java:511)
09-08 14:13:21.577: I/dalvikvm(16536): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:823)
09-08 14:13:21.577: I/dalvikvm(16536): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:590)
09-08 14:13:21.577: I/dalvikvm(16536): at dalvik.system.NativeStart.main(Native Method)
09-08 14:13:21.577: D/AndroidRuntime(16536): Shutting down VM
09-08 14:13:21.577: W/dalvikvm(16536): threadid=1: thread exiting with uncaught exception (group=0x40ad1210)
09-08 14:13:21.597: E/AndroidRuntime(16536): FATAL EXCEPTION: main
09-08 14:13:21.597: E/AndroidRuntime(16536): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.test/com.test.IndexActivity}: android.view.InflateException: Binary XML file line #1: Error inflating class <unknown>
09-08 14:13:21.597: E/AndroidRuntime(16536): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1967)
09-08 14:13:21.597: E/AndroidRuntime(16536): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1992)
09-08 14:13:21.597: E/AndroidRuntime(16536): at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:3371)
09-08 14:13:21.597: E/AndroidRuntime(16536): at android.app.ActivityThread.access$700(ActivityThread.java:127)
09-08 14:13:21.597: E/AndroidRuntime(16536): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1162)
09-08 14:13:21.597: E/AndroidRuntime(16536): at android.os.Handler.dispatchMessage(Handler.java:99)
09-08 14:13:21.597: E/AndroidRuntime(16536): at android.os.Looper.loop(Looper.java:137)
09-08 14:13:21.597: E/AndroidRuntime(16536): at android.app.ActivityThread.main(ActivityThread.java:4441)
09-08 14:13:21.597: E/AndroidRuntime(16536): at java.lang.reflect.Method.invokeNative(Native Method)
09-08 14:13:21.597: E/AndroidRuntime(16536): at java.lang.reflect.Method.invoke(Method.java:511)
09-08 14:13:21.597: E/AndroidRuntime(16536): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:823)
09-08 14:13:21.597: E/AndroidRuntime(16536): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:590)
09-08 14:13:21.597: E/AndroidRuntime(16536): at dalvik.system.NativeStart.main(Native Method)
09-08 14:13:21.597: E/AndroidRuntime(16536): Caused by: android.view.InflateException: Binary XML file line #1: Error inflating class <unknown>
09-08 14:13:21.597: E/AndroidRuntime(16536): at android.view.LayoutInflater.createView(LayoutInflater.java:606)
09-08 14:13:21.597: E/AndroidRuntime(16536): at com.android.internal.policy.impl.PhoneLayoutInflater.onCreateView(PhoneLayoutInflater.java:56)
09-08 14:13:21.597: E/AndroidRuntime(16536): at android.view.LayoutInflater.onCreateView(LayoutInflater.java:653)
09-08 14:13:21.597: E/AndroidRuntime(16536): at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:678)
09-08 14:13:21.597: E/AndroidRuntime(16536): at android.view.LayoutInflater.inflate(LayoutInflater.java:466)
09-08 14:13:21.597: E/AndroidRuntime(16536): at android.view.LayoutInflater.inflate(LayoutInflater.java:396)
09-08 14:13:21.597: E/AndroidRuntime(16536): at android.view.LayoutInflater.inflate(LayoutInflater.java:352)
09-08 14:13:21.597: E/AndroidRuntime(16536): at com.android.internal.policy.impl.PhoneWindow.setContentView(PhoneWindow.java:255)
09-08 14:13:21.597: E/AndroidRuntime(16536): at android.app.Activity.setContentView(Activity.java:1835)
09-08 14:13:21.597: E/AndroidRuntime(16536): at com.rahpou.android.parnian.IndexActivity.onCreate(IndexActivity.java:58)
09-08 14:13:21.597: E/AndroidRuntime(16536): at android.app.Activity.performCreate(Activity.java:4465)
09-08 14:13:21.597: E/AndroidRuntime(16536): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1049)
09-08 14:13:21.597: E/AndroidRuntime(16536): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1931)
09-08 14:13:21.597: E/AndroidRuntime(16536): ... 12 more
09-08 14:13:21.597: E/AndroidRuntime(16536): Caused by: java.lang.reflect.InvocationTargetException
09-08 14:13:21.597: E/AndroidRuntime(16536): at java.lang.reflect.Constructor.constructNative(Native Method)
09-08 14:13:21.597: E/AndroidRuntime(16536): at java.lang.reflect.Constructor.newInstance(Constructor.java:417)
09-08 14:13:21.597: E/AndroidRuntime(16536): at android.view.LayoutInflater.createView(LayoutInflater.java:586)
09-08 14:13:21.597: E/AndroidRuntime(16536): ... 24 more
09-08 14:13:21.597: E/AndroidRuntime(16536): Caused by: java.lang.OutOfMemoryError
09-08 14:13:21.597: E/AndroidRuntime(16536): at android.graphics.Bitmap.nativeCreate(Native Method)
09-08 14:13:21.597: E/AndroidRuntime(16536): at android.graphics.Bitmap.createBitmap(Bitmap.java:605)
09-08 14:13:21.597: E/AndroidRuntime(16536): at android.graphics.Bitmap.createBitmap(Bitmap.java:551)
09-08 14:13:21.597: E/AndroidRuntime(16536): at android.graphics.Bitmap.createScaledBitmap(Bitmap.java:437)
09-08 14:13:21.597: E/AndroidRuntime(16536): at android.graphics.BitmapFactory.finishDecode(BitmapFactory.java:530)
09-08 14:13:21.597: E/AndroidRuntime(16536): at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:505)
09-08 14:13:21.597: E/AndroidRuntime(16536): at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:357)
09-08 14:13:21.597: E/AndroidRuntime(16536): at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:777)
09-08 14:13:21.597: E/AndroidRuntime(16536): at android.content.res.Resources.loadDrawable(Resources.java:1940)
09-08 14:13:21.597: E/AndroidRuntime(16536): at android.content.res.TypedArray.getDrawable(TypedArray.java:601)
09-08 14:13:21.597: E/AndroidRuntime(16536): at android.view.View.<init>(View.java:2844)
09-08 14:13:21.597: E/AndroidRuntime(16536): at android.view.View.<init>(View.java:2781)
09-08 14:13:21.597: E/AndroidRuntime(16536): at android.view.ViewGroup.<init>(ViewGroup.java:412)
09-08 14:13:21.597: E/AndroidRuntime(16536): at android.widget.RelativeLayout.<init>(RelativeLayout.java:179)
09-08 14:13:21.597: E/AndroidRuntime(16536): ... 27 more
Il semble que le chargement d'un autre drawable coûte trop cher, mais j'ai vu beaucoup d'applications utilisant des graphiques et des fonds d'écran grands et variés et n'ayant aucun problème. Alors, comment puis-je empêcher cette fuite de mémoire et aider Android à recycler/détruire le précédent drawable d'arrière-plan pour éviter le OutOfMemory !
si c'est important, l'écran de mon téléphone et les fonds d'écran ont une résolution HD (720p), et les deux fonds d'écran (port et terre) font environ 100 Ko.
EDIT : J'ai essayé la première réponse et je l'ai modifiée dans mon code car j'ai une ScrollView
en tant que vue racine et les fonds d'écran sont définis sur son fond d'écran.
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
ScrollView root = (ScrollView)findViewById(R.id.root);
// this line causes NullPointerException:
BitmapDrawable drawable = (BitmapDrawable) root.getBackground();
Bitmap bitmap = drawable.getBitmap();
if (bitmap != null)
{
bitmap.recycle();
}
}
mais les choses ont empiré et j'ai eu NullPointerException
au premier changement d'orientation sur la ligne spécifiée dans le code.
Une autre question est de savoir pourquoi il faut allouer 16 Mo de mémoire pour créer un bitmap HD ? !! Je pense que 1280px x 800px x 8(bytes/pixel) = 8 MB alors pourquoi 16 MB sont nécessaires ? !! (Je me réfère à la première ligne du LogCat où il est écrit "Out of memory on a 16384016-byte allocation." et 16384016-byte ~ 16 MB.