3 votes

Crash de l'application lors d'un changement d'orientation (uniquement lorsque j'ai défini 2 arrière-plans différents pour les modes portrait et paysage)

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.

0voto

breceivemail Points 8024

Utilisez le code suivant.

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);            

    myImage = findViewById(R.id.myImage);
    BitmapDrawable drawable = (BitmapDrawable) myImage.getDrawable();
    Bitmap bitmap = drawable.getBitmap();
    if (bitmap != null)
    {
        bitmap.recycle();
    }       
}

et en manifeste :

<activity
  ...
    android:configChanges="keyboardHidden|orientation"
  ...
>
</activity>

0voto

Rajendra Points 1118

Ajoutez simplement ceci dans votre mainfest.xml

si votre Android:targetSdkVersion="12" ou moins

    android:configChanges="orientation|keyboardHidden">

si votre Android:targetSdkVersion="13" ou plus

    android:configChanges="orientation|keyboardHidden|screensize">

0voto

Andy Res Points 6837

Les réponses avec configChanges semblent atténuer le problème pour le moment, mais si nous jetons un coup d'œil à LogCat, nous constatons qu'il a une OutOfMemoryException .

C'est le résultat du chargement d'un grand bitmap, alors qu'il n'y a pas assez de mémoire à allouer.

Je vous suggère de jeter un coup d'œil à la documentation d'Android sur la façon de réparer : http://developer.Android.com/training/displaying-bitmaps/index.html

0voto

kronosXXI Points 176

Je suppose que vous avez déjà résolu ce problème, mais voici la solution que j'ai trouvée grâce à vos réponses.

J'ai utilisé deux ID différents pour la mise en page, et la fonction OnConfigurationChanged suivante :

@Override
public void onConfigurationChanged(Configuration newConfig) {
    BitmapDrawable drawable = null;
    if (findViewById(R.id.root_land) != null) {
        drawable = (BitmapDrawable) findViewById(R.id.root_land).getBackground();
    }
    if (findViewById(R.id.root_port) != null) {
        drawable = (BitmapDrawable) findViewById(R.id.root_port).getBackground();   

    }
    if (drawable != null){
        Bitmap bitmap = drawable.getBitmap();
        if (bitmap != null) {
            bitmap.recycle();
        }
    }
    super.onConfigurationChanged(newConfig);
    setContentView(R.layout.activity_main);
}

Et dans le manifeste (dans l'activité), je mets ceci :

android:configChanges="orientation|keyboardHidden|screensize">

0voto

Dimpal Chavan Points 21

J'ai utilisé System.gc() sur public void onConfigurationChanged méthode :

@Override
public void onConfigurationChanged(Configuration newConfig) {
    System.gc();
    super.onConfigurationChanged(newConfig);
    setContentView(R.layout.activity_main);
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X